bzoj4012 [HNOI2015]开店
树分治。以递归的顺序建造一个重心树,每层用数组维护所有点按年龄从小到大排序后,其到当前层重心的前缀和。询问时在每一层算出需要经过该层重心才能到达查询点的距离和,累加就是答案,该操作可以用之前维护的信息来进行操作,具体看代码。复杂度O(nlogn^2)
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<set> 5 #define fi first 6 #define sc second 7 #define pb push_back 8 #define mp make_pair 9 #define N 400010 10 #define M 20000000 11 #define lb(x) (x&-x) 12 using namespace std; 13 typedef long long ll; 14 int a[N],n,m,i,tot,root,q,f[N]; 15 int dp,p[N],pre[N],tt[N],s[N],flag[N],ww[N],deep[N]; 16 int L[N],R[N],LL[N],RR[N]; 17 int jump[N][20]; 18 ll ans,dist[N]; 19 struct g{ 20 int v;ll dis; 21 void set(int a,ll b) 22 { 23 v=a; 24 dis=b; 25 } 26 }e[M]; 27 bool operator <(g a,g b){return a.v<b.v;} 28 void link(int x,int y,int z) 29 { 30 dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;ww[dp]=z; 31 } 32 void getroot(int x,int fa,int size) 33 { 34 int i=p[x],fg=0; 35 s[x]=1; 36 while (i) 37 { 38 if ((tt[i]!=fa)&&(!flag[tt[i]])) 39 { 40 getroot(tt[i],x,size); 41 s[x]+=s[tt[i]]; 42 if (s[tt[i]]>size/2) fg=1; 43 } 44 i=pre[i]; 45 } 46 if (size-s[x]>size/2) fg=1; 47 if (!fg) root=x; 48 } 49 void get(int x,int fa,ll dis) 50 { 51 int i=p[x]; 52 e[++tot].set(a[x],dis); 53 while (i) 54 { 55 if ((!flag[tt[i]])&&(tt[i]!=fa)) 56 get(tt[i],x,dis+ww[i]); 57 i=pre[i]; 58 } 59 } 60 int find(int x,int y) 61 { 62 int i=p[x]; 63 while (i) 64 { 65 if (tt[i]==y) return ww[i]; 66 i=pre[i]; 67 } 68 } 69 void dfs(int x,int fa,int size) 70 { 71 int i,rt,tx=x; 72 getroot(x,0,size); 73 x=root;f[x]=fa; 74 flag[x]=1; 75 i=p[x]; 76 while (i) 77 { 78 if (!flag[tt[i]]) 79 { 80 if (s[tt[i]]<s[x]) 81 dfs(tt[i],x,s[tt[i]]); 82 else 83 dfs(tt[i],x,size-s[x]); 84 } 85 i=pre[i]; 86 } 87 L[x]=tot+1; 88 get(x,0,0); 89 R[x]=tot; 90 sort(e+L[x],e+1+R[x]); 91 for (i=L[x]+1;i<=R[x];i++) e[i].dis+=e[i-1].dis; 92 93 flag[x]=0; 94 if (f[x]) 95 { 96 LL[x]=tot+1; 97 get(tx,f[x],find(f[x],tx)); 98 RR[x]=tot; 99 sort(e+LL[x],e+1+RR[x]); 100 for (i=LL[x]+1;i<=RR[x];i++) e[i].dis+=e[i-1].dis; 101 } 102 } 103 void gao(int x,int fa) 104 { 105 int i; 106 deep[x]=deep[fa]+1; 107 jump[x][0]=fa; 108 for (i=1;i<=18;i++) 109 jump[x][i]=jump[jump[x][i-1]][i-1]; 110 i=p[x]; 111 while (i) 112 { 113 if (tt[i]!=fa) 114 { 115 dist[tt[i]]=dist[x]+ww[i]; 116 gao(tt[i],x); 117 } 118 i=pre[i]; 119 } 120 } 121 int lca(int a,int b) 122 { 123 int i; 124 if (deep[a]<deep[b]) a^=b^=a^=b; 125 for (i=18;i>=0;i--) 126 if (deep[jump[a][i]]>=deep[b]) a=jump[a][i]; 127 if (a==b) return a; 128 for (i=18;i>=0;i--) 129 if (jump[a][i]!=jump[b][i]) 130 { 131 a=jump[a][i];b=jump[b][i]; 132 } 133 return jump[a][0]; 134 } 135 pair<ll,ll> ef(int l,int r,int x) 136 { 137 int m,tmp=l; 138 while (l<=r) 139 { 140 m=(l+r)>>1; 141 if (e[m].v>x) r=m-1;else l=m+1; 142 } 143 ll dis=0; 144 if (r>=tmp) dis=e[r].dis; 145 return mp(r-tmp+1,dis); 146 } 147 ll query(int x,int a,int b) 148 { 149 int tx=x; 150 ll ans=0; 151 while (x) 152 { 153 pair<ll,ll> l=ef(L[x],R[x],a-1); 154 pair<ll,ll> r=ef(L[x],R[x],b); 155 ans+=r.sc-l.sc+(r.fi-l.fi)*(dist[tx]+dist[x]-2*dist[lca(tx,x)]); 156 157 if (f[x]) 158 { 159 pair<ll,ll> l=ef(LL[x],RR[x],a-1); 160 pair<ll,ll> r=ef(LL[x],RR[x],b); 161 ans-=(r.sc-l.sc+(r.fi-l.fi)*(dist[tx]+dist[f[x]]-2*dist[lca(tx,f[x])])); 162 } 163 x=f[x]; 164 } 165 return ans; 166 } 167 int main() 168 { 169 scanf("%d%d%d",&n,&q,&m); 170 for (i=1;i<=n;i++) 171 //a[i]=0; 172 scanf("%d",&a[i]); 173 for (i=1;i<n;i++) 174 { 175 int u,v,w; 176 //u=i;v=i+1;w=1000; 177 scanf("%d%d%d",&u,&v,&w); 178 link(u,v,w);link(v,u,w); 179 } 180 dfs(1,0,n); 181 deep[0]=-1;gao(1,0); 182 for (i=1;i<=q;i++) 183 { 184 int u,v,w; 185 scanf("%d%d%d",&u,&v,&w); 186 int ql,qr; 187 ql=min((v+ans)%m,(w+ans)%m); 188 qr=max((v+ans)%m,(w+ans)%m); 189 ans=query(u,ql,qr); 190 printf("%lld\n",ans); 191 } 192 193 }