题目大意:给一颗无根带边权树。支持两种操作:
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;
} 
京公网安备 11010502036488号