http://www.lydsy.com/JudgeOnline/problem.php?id=4012
动态树分治。
做过上一题捉迷藏,对动态树分治有了更深的认识。
”所有顶点的度数都小于或等于3“,好强的暗示。
类似的做法,先求重心,对于与重心相连的每棵子树,求出到每棵子树中所有点到重心的距离。每棵子树中的点按年龄排序,并求距离的前缀和。
然后递归即可。
对于询问,因为每个点最多“属于”$logn$个重心,在这$logn$个重心所对应的树中二分即可。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define fill(a,l,r,v) fill(a+l,a+r+1,v) #define re(i,a,b) for(i=(a);i<=(b);i++) #define red(i,a,b) for(i=(a);i>=(b);i--) #define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define p_b(a) push_back(a) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxn=150000; int n,Q,A; int age[maxn+100]; int now[2],info[2][maxn+100]; struct Tedge{int v,cost,next,kind;}edge[2][maxn*20]; void addedge(int k,int u,int v,int cost,int kind=0) { edge[k][++now[k]]=k?(Tedge){v,cost,info[k][u],kind}:(Tedge){v,cost,info[k][u],0}; info[k][u]=now[k]; } struct Tdata { int age,dist;LL sum; Tdata(int _age=0,int _dist=0){age=_age;dist=_dist;sum=0;} friend bool const operator <(const Tdata a,const Tdata b){return a.age<b.age;} }; int num; int mark[maxn+100],gen[maxn+100],degree[maxn+100]; vector<Tdata> S[maxn+100][4]; int sz[maxn+100],mx[maxn+100]; void getrt(int u,int fa,int all,int &rt) { int i,v; sz[u]=1;mx[u]=0; for(i=info[0][u],v=edge[0][i].v;i!=-1;i=edge[0][i].next,v=edge[0][i].v)if(!mark[v] && v!=fa)getrt(v,u,all,rt),sz[u]+=sz[v],upmax(mx[u],sz[v]); upmax(mx[u],all-sz[u]); if(!rt || mx[u]<mx[rt])rt=u; } void dfs(int u,int fa,int dist,int cur,int kind) { S[cur][kind].p_b(Tdata(age[u],dist)); addedge(1,u,cur,dist,kind); int i,v,cost; for(i=info[0][u],v=edge[0][i].v,cost=edge[0][i].cost;i!=-1;i=edge[0][i].next,v=edge[0][i].v,cost=edge[0][i].cost)if(!mark[v] && v!=fa)dfs(v,u,dist+cost,cur,kind); } void prep(int u,int all) { if(all<=1)return; int i,j,rt=0,tmp=0; getrt(u,-1,all,rt); getrt(rt,-1,all,tmp); int cur=++num,v,cost; mark[rt]=cur;gen[cur]=rt;degree[cur]=0; addedge(1,rt,cur,0,0); for(i=info[0][rt],v=edge[0][i].v,cost=edge[0][i].cost;i!=-1;i=edge[0][i].next,v=edge[0][i].v,cost=edge[0][i].cost)if(!mark[v]) { int t=++degree[cur]; dfs(v,rt,cost,cur,t); sort(S[cur][t].begin(),S[cur][t].end()); S[cur][t][0].sum=S[cur][t][0].dist;re(j,1,int(S[cur][t].size())-1)S[cur][t][j].sum=S[cur][t][j-1].sum+S[cur][t][j].dist; prep(v,sz[v]); } } LL ask(int x,int M) { int i,j,cur,dis,kind;LL res=0; for(i=info[1][x],cur=edge[1][i].v,dis=edge[1][i].cost,kind=edge[1][i].kind;i!=-1;i=edge[1][i].next,cur=edge[1][i].v,dis=edge[1][i].cost,kind=edge[1][i].kind) { if(age[gen[cur]]<=M)res+=dis; re(j,1,degree[cur])if(j!=kind) { vector<Tdata>::iterator it=upper_bound(S[cur][j].begin(),S[cur][j].end(),Tdata(M)); if(it==S[cur][j].begin())continue; it--; res+=it->sum+1LL*(it-S[cur][j].begin()+1)*dis; } } return res; } int main() { freopen("bzoj4012.in","r",stdin); freopen("bzoj4012.out","w",stdout); int i; n=gint();Q=gint();A=gint(); re(i,1,n)age[i]=gint(); mmst(now,-1);mmst(info,-1); re(i,1,n-1){int u=gint(),v=gint(),cost=gint();addedge(0,u,v,cost);addedge(0,v,u,cost);} prep(1,n); LL lastans=0; while(Q--) { int x=gint(),a=gint(),b=gint(),L=(LL(a)+lastans)%LL(A),R=(LL(b)+lastans)%LL(A); if(L>R)swap(L,R); lastans=ask(x,R)-ask(x,L-1); PF("%I64d ",lastans); } return 0; }