P6845 [CEOI 2019] Dynamic Diameter
钦定一个根,考虑用数据结构维护维护节点深度,这是好做的。再用一颗线段树维护直径,对于修改,把跟节点到修改区间上的点全部 \(push\_up\) 一次就可以了。
代码
#include<bits/stdc++.h>
using namespace std;
namespace IO{
template<typename T>
inline void read(T&x){
x=0;char c=getchar();bool f=0;
while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
f?x=-x:0;
}
template<typename T>
inline void write(T x){
if(x==0){putchar('0');return ;}
x<0?x=-x,putchar('-'):0;short st[50],top=0;
while(x) st[++top]=x%10,x/=10;
while(top) putchar(st[top--]+'0');
}
inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
inline void write(char c){putchar(c);}
inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
#define int long long
#define LL long long
const int maxn=100010;
int n,q,dfn[maxn],cnt,dfn_out[maxn],deep[maxn],fan[maxn],fa[maxn];
LL w;
struct EDGE{int u,v;LL w;}b[maxn];
vector<pair<int,LL>>e[maxn];
inline void dfs(int u,int fa=0){
::fa[u]=fa;
deep[u]=deep[fa]+1;
dfn[u]=++cnt;fan[cnt]=u;
for(auto i:e[u]){
int v=i.first;
if(v==fa) continue;
dfs(v,u);
}
dfn_out[u]=cnt;
}
template<typename T>class ST{
private:
T st[maxn][20];
int lg[maxn];
public:
inline void build(T a[]){
for(int i=1;i<=n;i++) st[i][0]=a[i],lg[i]=__lg(i);
lg[0]=1;
for(int j=1;j<=17;j++) for(int i=1;i<=n;i++){
int k=i+(1<<j-1);
if(k>n) k=n;
st[i][j]=min(st[i][j-1],st[k][j-1]);
}
}
inline T query(int l,int r){
int lgg=lg[r-l+1];
return min(st[l][lgg],st[r-(1<<lgg)+1][lgg]);
}
};
struct node_for_cmp{
int first,second;
inline bool operator<(const node_for_cmp t)const{return first<t.first;}
};
node_for_cmp pair_for_build[maxn];
ST<node_for_cmp>st;
inline int lca(int u,int v){
if(u==v) return u;
int w=dfn[u],ww=dfn[v];
if(w>ww) swap(w,ww);
node_for_cmp l=st.query(w+1,ww);
return fa[l.second];
}
class BIT_for_Dis{
private:
int t[maxn];
int low(int u){return u&-u;}
void update(int u,int add){while(u<=n) t[u]+=add,u+=low(u);}
int query(int u){int ans=0;while(u) ans+=t[u],u-=low(u);return ans;}
public:
inline void update(int l,int r,LL z){update(l,z),update(r+1,-z);}
inline int operator[](const int wz){return query(wz);}
}d;
inline LL get_dis(int u,int v){
u=fan[u],v=fan[v];
int l=lca(u,v);
return d[dfn[u]]+d[dfn[v]]-d[dfn[l]]*2;
}
class Segment_Tree_for_Diameter{
private:
struct node{int d1,d2;}t[maxn*8];
inline node merge(node a,node b){
int d[]={0,a.d1,a.d2,b.d1,b.d2};
int maxd1,maxd2;
LL maxx=0;
for(int i=1;i<=4;++i) for(int j=1;j<i;++j){
int d1=d[i],d2=d[j];
if(!d1||!d2) continue;
LL new_dis=get_dis(d1,d2);
if(new_dis>=maxx) maxx=new_dis,maxd1=d1,maxd2=d2;
}
return(node){maxd1,maxd2};
}
inline void push_up(int u){t[u]=merge(t[u<<1],t[u<<1|1]);}
inline void update(int u,int l,int r,int ll,int rr){
if(l>rr||r<ll) return ;
if(ll<=l&&r<=rr) return ;
int mid=l+r>>1;
update(u<<1,l,mid,ll,rr),update(u<<1|1,mid+1,r,ll,rr);
push_up(u);
}
public:
inline void update(int l,int r){update(1,1,n,l,r);}
inline LL query(){return get_dis(t[1].d1,t[1].d2);}
inline void build(int u=1,int l=1,int r=n){
if(l==r){t[u].d1=t[u].d2=l;return ;}
int mid=l+r>>1;
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
push_up(u);
}
}t;
signed main(){
read(n,q,w);
for(int i=1;i<n;i++){
int u,v;LL w;read(u,v,w);
b[i]={u,v,w};
e[u].push_back({v,w}),e[v].push_back({u,w});
}
for(int i=1;i<=n;i++) d.update(i,i,0);
dfs(1);
for(int i=1;i<=n;i++) pair_for_build[dfn[i]]={deep[i],i};
st.build(pair_for_build);
for(int u=1;u<=n;u++) for(auto i:e[u]){
int v=i.first;
if(deep[u]<deep[v]) continue;
d.update(dfn[u],dfn_out[u],i.second);
}
t.build();
LL ltans=0;
for(int i=1;i<=q;i++){
int d;
LL e;read(d,e);
d=(d+ltans)%(n-1)+1;e=(e+ltans)%w;
LL add=e-b[d].w;
b[d].w=e;
if(deep[b[d].u]>deep[b[d].v]) d=b[d].u;
else d=b[d].v;
::d.update(dfn[d],dfn_out[d],add);
t.update(dfn[d],dfn_out[d]);
write(ltans=t.query());write("\n");
}
return 0;
}

浙公网安备 33010602011771号