题目大意:给一颗无根带边权树。支持两种操作:
1、修改某条边的边权。
2、查询当前直径。
点分树模板题,全局开一个multiset维护直径,对于每个重心开一颗线段树和一个局部multiset,用欧拉序线段树维护每一个子树中的最值,然后将其放入局部multiset。接下来取局部multiset中前两大的路径合并扔到全局multiset中,每次直接输出全局multiset的最大值即可。
#include<bits/stdc++.h> using namespace std; const int MAXN=200005,MAXM=400005,MAXBIT=19; struct tnode { long long max1,lazy; int l,r; }; struct Segment_Tree { vector<tnode>t; void pushdown(int root) { if(t[root].lazy!=0) { t[root].max1+=t[root].lazy; if(t[root].l!=t[root].r) { int ch=root<<1; t[ch].lazy+=t[root].lazy; t[ch+1].lazy+=t[root].lazy; } t[root].lazy=0; } } void update (int root) { int ch=root<<1; pushdown(ch); pushdown(ch+1); t[root].max1=max(t[ch].max1,t[ch+1].max1); } void init(const long long A[],int n) { t.resize(4*n); buildit(1,1,n,A); } void buildit(int root,int l,int r,const long long A[]) { t[root].l=l; t[root].r=r; t[root].lazy=0; if(l!=r) { int mid=(l+r)>>1; int ch=root<<1; buildit(ch,l,mid,A); buildit(ch+1,mid+1,r,A); update(root); } else t[root].max1=A[l]; } void change(int root,int l,int r,long long delta) { pushdown(root); if(l==t[root].l&&r==t[root].r) { t[root].lazy+=delta; pushdown(root); return; } int mid=(t[root].l+t[root].r)>>1; int ch=root<<1; if(r<=mid)change(ch,l,r,delta); else if(l>mid)change(ch+1,l,r,delta); else { change(ch,l,mid,delta); change(ch+1,mid+1,r,delta); } update(root); } long long qmax(int root,int l,int r) { pushdown(root); if(t[root].l==l&&t[root].r==r) { return t[root].max1; } int mid=(t[root].l+t[root].r)>>1; int ch=root<<1; if(r<=mid)return qmax(ch,l,r); else if(l>mid)return qmax(ch+1,l,r); else return max(qmax(ch,l,mid),qmax(ch+1,mid+1,r)); } }; Segment_Tree ST[MAXN]; int n,q,u,v,g[MAXN],tot,gravity_size[MAXN],gravity_max[MAXN],gravity,siz,g_deep[MAXN],belone[MAXN][MAXBIT],L[MAXN][MAXBIT],R[MAXN][MAXBIT],chain_top[MAXN][MAXBIT],dfn,g_fa[MAXN]; long long p_val[MAXN],temp_val[MAXN],W,last_ans,dj,ej; bool div_vis[MAXN]; multiset<long long>tans[MAXN],ans; struct edges { int to; int next; } e[MAXM<<1]; void add_edge(int from,int to) { e[++tot].to=to; e[tot].next=g[from]; g[from]=tot; return; } void get_gravity(int x,int fa) { gravity_size[x]=1; gravity_max[x]=-1; for(int i=g[x]; i; i=e[i].next) { if(e[i].to!=fa&&!div_vis[e[i].to]) { get_gravity(e[i].to,x); if(gravity_max[x]==-1||gravity_max[x]<gravity_size[e[i].to]) { gravity_max[x]=gravity_size[e[i].to]; } gravity_size[x]+=gravity_size[e[i].to]; } } gravity_max[x]=max(gravity_max[x],siz-gravity_size[x]); if(gravity==-1||gravity_max[gravity]>gravity_max[x])gravity=x; } void get_size(int x,int fa) { ++siz; for(int i=g[x]; i; i=e[i].next) { if(e[i].to!=fa&&!div_vis[e[i].to]) { get_size(e[i].to,x); } } } void dfs_get_date(int now,int fa,int c_top,long long nowsum,const int &state) { L[now][state]=++dfn; belone[now][state]=gravity; if(gravity==c_top) { c_top=now; } chain_top[now][state]=c_top; temp_val[dfn]=nowsum; for(int i=g[now]; i; i=e[i].next) { if(e[i].to!=fa&&!div_vis[e[i].to]) { dfs_get_date(e[i].to,now,c_top,nowsum+p_val[e[i].to],state); } } R[now][state]=dfn; } long long get_template_ans(int now) { if(tans[now].size()>=2) { multiset<long long>::reverse_iterator it=tans[now].rbegin(); it++; return *tans[now].rbegin()+*it; } return *tans[gravity].rbegin(); } void tree_div(int x,int pre,int deep) { siz=0; get_size(x,-1); gravity=-1; get_gravity(x,-1); div_vis[gravity]=true; g_deep[gravity]=deep; dfn=0; dfs_get_date(gravity,-1,gravity,0,deep); ST[gravity].init(temp_val,siz); tans[gravity].insert(0); for(int i=g[gravity]; i; i=e[i].next) { if(!div_vis[e[i].to]) { tans[gravity].insert(ST[gravity].qmax(1,L[e[i].to][deep],R[e[i].to][deep])); } } ans.insert(get_template_ans(gravity)+p_val[gravity]); int t_g=gravity; g_fa[t_g]=pre; for(int i=g[gravity]; i; i=e[i].next) { if(!div_vis[e[i].to]) { tree_div(e[i].to,t_g,deep+1); } } return; } void change(int now_g,int now_p,long long preval,long long nowval) { while(now_g) { int now_top=chain_top[now_p][g_deep[now_g]]; if(now_top==now_g) { ans.erase(ans.find(get_template_ans(now_g)+preval)); ans.insert(get_template_ans(now_g)+nowval); } else { ans.erase(ans.find(get_template_ans(now_g)+p_val[now_g])); long long t_temp=ST[now_g].qmax(1,L[now_top][g_deep[now_g]],R[now_top][g_deep[now_g]]); tans[now_g].erase(tans[now_g].find(t_temp)); ST[now_g].change(1,L[now_p][g_deep[now_g]],R[now_p][g_deep[now_g]],nowval-preval); t_temp=ST[now_g].qmax(1,L[now_top][g_deep[now_g]],R[now_top][g_deep[now_g]]); tans[now_g].insert(t_temp); ans.insert(get_template_ans(now_g)+p_val[now_g]); } now_g=g_fa[now_g]; } p_val[now_p]=nowval; } int main() { scanf("%d %d %lld",&n,&q,&W); for(int i=1; i<n; ++i) { scanf("%d %d %lld",&u,&v,&p_val[n+i]); add_edge(u,n+i); add_edge(n+i,u); add_edge(v,n+i); add_edge(n+i,v); } tree_div(1,0,0); while(q--) { scanf("%lld %lld",&dj,&ej); dj=(dj+last_ans)%(n-1); ej=(ej+last_ans)%W; change(dj+n+1,dj+n+1,p_val[dj+n+1],ej); last_ans=*ans.rbegin(); printf("%lld\n",last_ans); } return 0; }