(UPD: 2024-12-04 14:48 UTC) Judge is not working due to Cloudflare incident. (URL) We can do nothing about it, sorry. After the incident is resolved, we will grade all submissions.

Submission #779493

#TimeUsernameProblemLanguageResultExecution timeMemory
779493sdgdgssdgDynamic Diameter (CEOI19_diameter)C++14
100 / 100
4572 ms185328 KiB
//diameter #include <bits/stdc++.h> #define MAX 205000 #define SMAX 5550000 #pragma GCC optimize("Ofast,unroll-loops") #pragma GCC target("avx2,popcnt,lzcnt,abm,bmi,bmi2,fma,tune=native") using ll = long long; typedef std::pair<int,int> pii; ll tab[SMAX*4],lazy[SMAX*4]; void propag(int pos){ tab[pos]+=lazy[pos]; if(pos*2<SMAX*4){ lazy[pos*2]+=lazy[pos]; lazy[(pos*2)+1]+=lazy[pos]; } lazy[pos]=0; } ll query(int l,int r,int la=0,int ra=SMAX-1,int pos=1){ propag(pos); if(la>r||ra<l)return 0; if(la>=l&&ra<=r){ return tab[pos]; } int m = (la+ra)/2; return std::max(query(l,r,la,m,pos*2),query(l,r,m+1,ra,(pos*2)+1)); } void lazyadd(int l,int r,ll k,int la=0,int ra=SMAX-1,int pos=1){ propag(pos); if(la>r||ra<l)return; if(la>=l&&ra<=r){ lazy[pos]+=k; propag(pos); return; } int m = (la+ra)/2; lazyadd(l,r,k,la,m,pos*2); lazyadd(l,r,k,m+1,ra,(pos*2)+1); tab[pos]=std::max(tab[pos*2],tab[(pos*2)+1]); } std::vector<pii> con[MAX]; ll N,Q,W; ll peso[MAX]; bool bloqueado[MAX]; inline int dfs(int pos,int prev){ int s=1; for(auto&x:con[pos]){ if(x.first==prev)continue; if(bloqueado[x.first])continue; s+=dfs(x.first,pos); } return s; } int centroide=0; inline int find_centroide(int pos,int prev,int sz){ int b=0; int c=1; for(auto&x:con[pos]){ if(x.first==prev)continue; if(bloqueado[x.first])continue; int d = find_centroide(x.first,pos,sz); b=std::max(b,d); c+=d; } if(std::max(b,sz-c)<=sz/2){ centroide=pos; } return c; } int cureuler=0; pii rangeeuler[MAX][20]; pii rangeedges[MAX][20]; int ancestralmaior[MAX][20]; int centronivel[MAX][20]; int valores[SMAX]; inline void montar_euler(int pos,int prev,int lvl,int C){ centronivel[pos][lvl]=C; ++cureuler; valores[cureuler]=pos; rangeeuler[pos][lvl].first=cureuler; for(auto&x:con[pos]){ if(x.first==prev)continue; if(bloqueado[x.first])continue; montar_euler(x.first,pos,lvl,C); } rangeeuler[pos][lvl].second=cureuler; } inline void setar_euler(int pos,int prev,int lvl,int paimax){ ancestralmaior[pos][lvl]=paimax; for(auto&x:con[pos]){ if(x.first==prev)continue; if(bloqueado[x.first])continue; rangeedges[x.second][lvl]=rangeeuler[x.first][lvl]; if(prev==-1) setar_euler(x.first,pos,lvl,x.first); else setar_euler(x.first,pos,lvl,paimax); } } int virou_centroide[MAX]; int farthest(int la,int ra){ ll goal=query(la,ra); int l=la,r=ra; while(l<r){ int m = (l+r)/2; if(query(la,m)==goal){ r=m; }else l=m+1; } return l; } ll pega_custo_otter(int otter,int lvl){ int C = centronivel[otter][lvl]; int maisdist=otter; if(maisdist==C)return query(rangeeuler[maisdist][lvl].first,rangeeuler[maisdist][lvl].first); ll pega = ancestralmaior[maisdist][lvl]; assert(pega!=-1); pii ragpai = rangeeuler[C][lvl]; ll p1 = query(rangeeuler[maisdist][lvl].first,rangeeuler[maisdist][lvl].first); pii ragfil = rangeeuler[pega][lvl]; ll p2 = std::max(query(ragpai.first,ragfil.first-1),query(ragfil.second+1,ragpai.second)); return p1+p2; } int raiz=0; void decompor_centroide(int X,int lvl=0){ int SZ = dfs(X,-1); find_centroide(X,-1,SZ); int C = centroide; virou_centroide[C]=lvl; ///Do centroid stuff montar_euler(C,-1,lvl,C); setar_euler(C,-1,lvl,-1); bloqueado[C]=1; if(!lvl)raiz=C; for(auto&x:con[C]){ if(!bloqueado[x.first])decompor_centroide(x.first,lvl+1); } } void altera_aresta(int X,ll novo){ ll delta = novo-peso[X]; for(int i=0;i!=20;++i){ if(rangeedges[X][i].first==0)continue; lazyadd(rangeedges[X][i].first,rangeedges[X][i].second,delta); } peso[X]=novo; } int main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); std::cin>>N>>Q>>W; for(int i=0;i!=N-1;++i){ ll a,b,c; std::cin>>a>>b>>c;--a;--b; con[a].push_back({b,i}); con[b].push_back({a,i}); peso[i]=c; } decompor_centroide(0); for(int i=0;i!=N-1;++i){ ll kek=peso[i]; peso[i]=0; altera_aresta(i,kek); } assert(cureuler<SMAX); ll last=0; for(int i=0;i!=Q;++i){ ll a,b; std::cin>>a>>b;a=(a+last)%(N-1);b=(b+last)%W; altera_aresta(a,b); ll best=0; int maisdist = valores[farthest(rangeeuler[raiz][0].first,rangeeuler[raiz][0].second)]; for(int i=0;i<=virou_centroide[maisdist];++i)best=std::max(best,pega_custo_otter(maisdist,i)); last=best; std::cout<<last<<"\n"; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...