这道题好像各位神犇都是用动态树分治写的,我这么弱只能用树剖水一水了。
dis(x,y)=dis(1,x)+dis(1,y)-dis(1,lca(x,y))
前两个都是定值,求第三项就行了。
每个点x维护不在重链上的子节点的个数*dis(1,x),查询显然,再yy一些别的东西就可以了。
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define ll long long #define inf 1e9 #define eps 1e-10 #define md #define N 150010 #define TR 20000000 using namespace std; struct yts { int x,t,l,ne;} e[2*N]; int n,td; int num,dfs_cnt,cnt; int dat[N],v[N],dep[N],sz[N],son[N],fa[N][20],pos[N],top[N],low[N],right[N],dis[N],root[N],s_sz[N]; ll s_dis[N]; ll sum[TR]; int size[TR],ch[TR][2],qs[TR]; struct AA { int age,pos;} a[N]; bool cmp(AA a,AA b) { return a.age<b.age;} void lisanhua() { <span style="white-space:pre"> </span>sort(a+1,a+n+1,cmp); <span style="white-space:pre"> </span>a[0].age=-1; int now=-1; dat[0]=-1; <span style="white-space:pre"> </span>for (int i=1;i<=n;i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if (a[i].age!=now) { dat[++td]=a[i].age; now=a[i].age;} <span style="white-space:pre"> </span>a[i].age=td; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>dat[td+1]=inf; <span style="white-space:pre"> </span>//for (int i=1;i<=td;i++) printf("%d ",dat[i]); printf("\n"); } void put(int x,int y,int l) { <span style="white-space:pre"> </span>num++; e[num].x=x; e[num].t=y; e[num].l=l; <span style="white-space:pre"> </span>e[num].ne=v[x]; v[x]=num; } void dfs1(int x) { <span style="white-space:pre"> </span>sz[x]=1; son[x]=0; <span style="white-space:pre"> </span>for (int i=v[x];i;i=e[i].ne) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int y=e[i].t; <span style="white-space:pre"> </span>if (y!=fa[x][0]) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fa[y][0]=x; dep[y]=dep[x]+1; dis[y]=dis[x]+e[i].l; <span style="white-space:pre"> </span>dfs1(y); <span style="white-space:pre"> </span>sz[x]+=sz[y]; if (sz[y]>sz[son[x]]) son[x]=y; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} } void dfs2(int x,int f) { <span style="white-space:pre"> </span>pos[x]=++dfs_cnt; top[x]=f; <span style="white-space:pre"> </span>if (son[x]) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>dfs2(son[x],f); <span style="white-space:pre"> </span>low[x]=low[son[x]]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>else low[x]=pos[x]; <span style="white-space:pre"> </span>for (int i=v[x];i;i=e[i].ne) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int y=e[i].t; <span style="white-space:pre"> </span>if (y!=fa[x][0]&&y!=son[x]) <span style="white-space:pre"> </span> dfs2(y,y); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>right[x]=dfs_cnt; } int find1(int x)//最小的大于等于x的。 { <span style="white-space:pre"> </span>int l=1,r=td+1; <span style="white-space:pre"> </span>while (l!=r) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int mid=(l+r)>>1; <span style="white-space:pre"> </span>if (dat[mid]>=x) r=mid; else l=mid+1; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return l; } int find2(int x)//最大的小于等于x的。 { <span style="white-space:pre"> </span>int l=0,r=td; <span style="white-space:pre"> </span>while (l!=r) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int mid=(l+r+1)>>1; <span style="white-space:pre"> </span>if (dat[mid]<=x) l=mid; else r=mid-1; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return l; } void build_lca() { <span style="white-space:pre"> </span>for (int j=1;j<=18;j++) <span style="white-space:pre"> </span> for (int i=1;i<=n;i++) <span style="white-space:pre"> </span> if (fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1]; } int lca(int x,int y) { <span style="white-space:pre"> </span>if (dep[x]<dep[y]) swap(x,y); <span style="white-space:pre"> </span>int t=dep[x]-dep[y]; <span style="white-space:pre"> </span>for (int i=18;i>=0;i--) <span style="white-space:pre"> </span> if (t&(1<<i)) x=fa[x][i]; <span style="white-space:pre"> </span>if (x==y) return x; <span style="white-space:pre"> </span>for (int i=18;i>=0;i--) <span style="white-space:pre"> </span> if (fa[x][i]!=fa[y][i]) <span style="white-space:pre"> </span> x=fa[x][i],y=fa[y][i]; <span style="white-space:pre"> </span>return fa[x][0]; } void insert_sz(int &i,int pre,int l,int r,int x) { <span style="white-space:pre"> </span>i=++cnt; <span style="white-space:pre"> </span>size[i]=size[pre]+1; sum[i]=sum[pre]; qs[i]=qs[pre]; <span style="white-space:pre"> </span>if (l==r) return; <span style="white-space:pre"> </span>int mid=(l+r)>>1; <span style="white-space:pre"> </span>if (x<=mid) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>insert_sz(ch[i][0],ch[pre][0],l,mid,x); <span style="white-space:pre"> </span>ch[i][1]=ch[pre][1]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>else <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>insert_sz(ch[i][1],ch[pre][1],mid+1,r,x); <span style="white-space:pre"> </span>ch[i][0]=ch[pre][0]; <span style="white-space:pre"> </span>} } void insert(int &i,int pre,int l,int r,int x,int dis) { <span style="white-space:pre"> </span>i=++cnt; <span style="white-space:pre"> </span>sum[i]=sum[pre]+dis; size[i]=size[pre]; qs[i]=qs[pre]+1; <span style="white-space:pre"> </span>if (l==r) return; <span style="white-space:pre"> </span>int mid=(l+r)>>1; <span style="white-space:pre"> </span>if (x<=mid) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>insert(ch[i][0],ch[pre][0],l,mid,x,dis); <span style="white-space:pre"> </span>ch[i][1]=ch[pre][1]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>else <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>insert(ch[i][1],ch[pre][1],mid+1,r,x,dis); <span style="white-space:pre"> </span>ch[i][0]=ch[pre][0]; <span style="white-space:pre"> </span>} } <span style="white-space:pre"> </span> ll query_sz(int L,int R,int l,int r,int ql,int qr) { <span style="white-space:pre"> </span>if (ql<=l&&r<=qr) return size[R]-size[L]; <span style="white-space:pre"> </span>int mid=(l+r)>>1; <span style="white-space:pre"> </span>if (qr<=mid) return query_sz(ch[L][0],ch[R][0],l,mid,ql,qr); <span style="white-space:pre"> </span>if (mid+1<=ql) return query_sz(ch[L][1],ch[R][1],mid+1,r,ql,qr); <span style="white-space:pre"> </span>return query_sz(ch[L][0],ch[R][0],l,mid,ql,qr)+query_sz(ch[L][1],ch[R][1],mid+1,r,ql,qr); } ll query(int L,int R,int l,int r,int ql,int qr) { <span style="white-space:pre"> </span>if (ql<=l&&r<=qr) return sum[R]-sum[L]; <span style="white-space:pre"> </span>int mid=(l+r)>>1; <span style="white-space:pre"> </span>if (qr<=mid) return query(ch[L][0],ch[R][0],l,mid,ql,qr); <span style="white-space:pre"> </span>if (mid+1<=ql) return query(ch[L][1],ch[R][1],mid+1,r,ql,qr); <span style="white-space:pre"> </span>return query(ch[L][0],ch[R][0],l,mid,ql,qr)+query(ch[L][1],ch[R][1],mid+1,r,ql,qr); } ll query_line(int L,int R,int l,int r,int ql,int qr) { <span style="white-space:pre"> </span>if (ql<=l&&r<=qr) return qs[R]-qs[L]; <span style="white-space:pre"> </span>int mid=(l+r)>>1; <span style="white-space:pre"> </span>if (qr<=mid) return query_line(ch[L][0],ch[R][0],l,mid,ql,qr); <span style="white-space:pre"> </span>if (mid+1<=ql) return query_line(ch[L][1],ch[R][1],mid+1,r,ql,qr); <span style="white-space:pre"> </span>return query_line(ch[L][0],ch[R][0],l,mid,ql,qr)+query_line(ch[L][1],ch[R][1],mid+1,r,ql,qr); } int main() { #ifndef ONLINE_JUDGE <span style="white-space:pre"> </span>freopen("data.in","r",stdin); freopen("b.out","w",stdout); #endif <span style="white-space:pre"> </span>int Q,A; <span style="white-space:pre"> </span>scanf("%d%d%d",&n,&Q,&A); <span style="white-space:pre"> </span>for (int i=1;i<=n;i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>scanf("%d",&a[i].age); <span style="white-space:pre"> </span>a[i].pos=i; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>for (int i=1;i<n;i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int x,y,l; <span style="white-space:pre"> </span>scanf("%d%d%d",&x,&y,&l); <span style="white-space:pre"> </span>put(x,y,l); put(y,x,l); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>dep[1]=1; dfs1(1); dfs2(1,1); build_lca(); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>lisanhua(); <span style="white-space:pre"> </span>int pre=0; <span style="white-space:pre"> </span>for (int i=1;i<=n;i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int x=a[i].pos; <span style="white-space:pre"> </span>insert_sz(root[a[i].age],pre,1,n,pos[x]); pre=root[a[i].age]; <span style="white-space:pre"> </span>s_sz[a[i].age]++; s_dis[a[i].age]+=dis[x]; <span style="white-space:pre"> </span>while (x) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>insert(root[a[i].age],pre,1,n,pos[x],dis[x]); pre=root[a[i].age]; <span style="white-space:pre"> </span>x=fa[top[x]][0]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>for (int i=1;i<=td;i++) s_sz[i]+=s_sz[i-1],s_dis[i]+=s_dis[i-1]; <span style="white-space:pre"> </span>ll ans=0; <span style="white-space:pre"> </span>for (int i=1;i<=Q;i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>int u,x,y; <span style="white-space:pre"> </span>scanf("%d%d%d",&u,&x,&y); <span style="white-space:pre"> </span>int L=(ans+x)%A,R=(ans+y)%A; <span style="white-space:pre"> </span>if (L>R) swap(L,R); <span style="white-space:pre"> </span>L=find1(L); R=find2(R); <span style="white-space:pre"> </span>if (L>td||R<1||L>R) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>ans=0; printf("0\n"); <span style="white-space:pre"> </span>continue; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>int rtL=root[L-1],rtR=root[R]; <span style="white-space:pre"> </span>x=u; <span style="white-space:pre"> </span>ans=((ll)dis[x])*(s_sz[R]-s_sz[L-1])+s_dis[R]-s_dis[L-1]; <span style="white-space:pre"> </span>ll jian=0; <span style="white-space:pre"> </span>while (x) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>jian+=query(rtL,rtR,1,n,pos[top[x]],pos[x]); <span style="white-space:pre"> </span>if (son[x]) jian+=query_line(rtL,rtR,1,n,pos[x]+1,low[x])*dis[x]; <span style="white-space:pre"> </span>x=top[x]; y=fa[x][0]; <span style="white-space:pre"> </span>if (y) jian-=query_sz(rtL,rtR,1,n,pos[x],right[x])*dis[y]; <span style="white-space:pre"> </span>x=y; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>ans=ans-jian*2; <span style="white-space:pre"> </span>printf("%lld\n",ans); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return 0; }