【BZOJ】4012: [HNOI2015]开店
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012
给出一个$n$个点的树,树上每一个点都有一个值$age$,每条边都有边权,每次查询一个点,求出树中所有点上权值${L<=age[i]<=R}$的点到它的距离的和。
为了学习传说中的动态树分治,我就把这个题当作模板题来写了。
当然这题也可以树链剖分+权值线段树。
为什么叫做动态树分治?其实就是把分治的结构记录了下来,树分治的好处在于每一次操作(找出当前块重心并再次递归)可以快速减少树的大小,我们记录下这个每次求出的树的重心的结构,这样的分治结构是严格log层的,每一次查询的是沿着分治结构构出的树往上跳,统计所有点到当前点的距离(这里需要数据结构维护,可以开一个vector动态记录每一个点在分治中所管辖的子树的所有点的信息,然后查询的时候二分即可),然后再往分治结构构成的树的父亲上跳,因为在分治结构的父亲所管辖的子树一定包含了当前点所管辖的子树,所以需要容斥(全是细节)。复杂度${O(nlog^{2})}$
可怕的是BZOJ上似乎卡常?
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 #include<ctime> 9 using namespace std; 10 #define maxn 600100 11 #define llg long long 12 #define RG register llg 13 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 14 llg Q,A,n,m,age[maxn],ans,dad[maxn],dadv[maxn],maxage,f[maxn][21],dis[maxn][21],deep[maxn]; 15 bool bj[maxn],bj_[maxn]; 16 llg g[maxn<<1],maxl,weizhi,dl[maxn],tail,L,R,o,te,buf[50]; 17 18 inline void write(RG x) 19 { 20 if (x<0) putchar('-'),x=-x; 21 buf[0]=0; 22 while (x) buf[++buf[0]]=x%10,x/=10; 23 if (!buf[0]) buf[0]=1,buf[1]=0; 24 while (buf[0]) putchar('0'+buf[buf[0]--]); 25 putchar('\n'); 26 } 27 28 inline llg getint() 29 { 30 llg w=0,q=0; 31 char c=getchar(); 32 while((c<'0' || c>'9') && c!='-') c=getchar(); 33 if (c=='-') q=1, c=getchar(); 34 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); 35 return q ? -w : w; 36 } 37 38 struct edge{ 39 int y,next; 40 llg d; 41 }e[maxn<<1]; 42 43 void addedge(RG x,RG y,RG d){ 44 e[++te].y=y; 45 e[te].d=d; 46 e[te].next=g[x]; 47 g[x]=te; 48 } 49 50 struct node 51 { 52 llg age,dis,qz,qz_,dis_; 53 }; 54 inline bool cmp(const node&a,const node&b) {return a.age<b.age;} 55 56 vector<node>c[maxn]; 57 58 inline void clear_() {for (RG i=1;i<=tail;i++) bj_[dl[i]]=0; tail=0;} 59 60 inline void dfs(RG x,RG fa) 61 { 62 for (RG i=g[x];i;i=e[i].next) 63 { 64 RG v=e[i].y; 65 if (v==fa) continue; 66 f[v][0]=x; dis[v][0]=e[i].d; 67 deep[v]=deep[x]+1; 68 dfs(v,x); 69 } 70 } 71 72 inline void make_f() 73 { 74 for (RG j=1;j<=17;j++) 75 for (RG i=1;i<=n;i++) 76 { 77 f[i][j]=f[f[i][j-1]][j-1]; 78 dis[i][j]=dis[i][j-1]+dis[f[i][j-1]][j-1]; 79 } 80 } 81 82 inline llg find_dis(RG x,RG y) 83 { 84 if (x==0 || y==0) return 0; 85 RG ans=0; 86 if (deep[x]<deep[y]) swap(x,y); 87 for (RG i=17;i>=0;i--) 88 if (deep[f[x][i]]>=deep[y]) 89 { 90 ans+=dis[x][i]; 91 x=f[x][i]; 92 } 93 if (x==y) return ans; 94 for (RG i=17;i>=0;i--) 95 if (f[x][i]!=f[y][i]) 96 { 97 ans+=dis[x][i]+dis[y][i]; 98 x=f[x][i],y=f[y][i]; 99 } 100 return ans+dis[x][0]+dis[y][0]; 101 } 102 103 void init() 104 { 105 RG x,y,z; 106 cin>>n>>Q>>A; 107 for (RG i=1;i<=n;i++) age[i]=getint(),maxage=max(maxage,age[i]); 108 for (RG i=1;i<n;i++) 109 { 110 x=getint(),y=getint(),z=getint(); 111 addedge(x,y,z); 112 addedge(y,x,z); 113 } 114 deep[1]=1; 115 dfs(1,0); 116 make_f(); 117 } 118 119 inline llg find_size(RG x) 120 { 121 bj_[x]=1; 122 dl[++tail]=x; 123 RG tot=1; 124 for (RG i=g[x];i;i=e[i].next) 125 { 126 RG v=e[i].y; 127 if (bj[v] || bj_[v]) continue; 128 tot+=find_size(v); 129 } 130 return tot; 131 } 132 133 inline llg dp(RG x,RG size) 134 { 135 bj_[x]=1; 136 dl[++tail]=x; 137 RG tot=1,ma=0; 138 for (register llg i=g[x];i;i=e[i].next) 139 { 140 RG v=e[i].y; 141 if (bj[v] || bj_[v]) continue; 142 RG he=dp(v,size); 143 ma=max(ma,he); 144 tot+=he; 145 } 146 ma=max(size-tot,ma); 147 if (ma<maxl) 148 { 149 maxl=ma; 150 weizhi=x; 151 } 152 return tot; 153 } 154 155 inline llg find_root(RG x) 156 { 157 clear_(); 158 RG size=find_size(x); 159 clear_(); 160 maxl=n+1; weizhi=-1; 161 dp(x,size); 162 return weizhi; 163 } 164 165 inline void dfs_c(RG x,RG now) 166 { 167 bj_[x]=1; dl[++tail]=x; 168 node E; 169 E.age=age[x]; E.dis=find_dis(x,now); E.dis_= find_dis(x,dad[now]); 170 c[now].push_back(E); 171 for (RG i=g[x];i;i=e[i].next) 172 { 173 RG v=e[i].y; 174 if (bj[v] || bj_[v]) continue; 175 dfs_c(v,now); 176 } 177 } 178 179 inline void solve( RG now,RG fa) 180 { 181 RG ne=find_root(now); 182 now=ne; 183 dadv[now]=find_dis(now,fa); 184 bj[now]=1; 185 dad[now]=fa; 186 clear_(); 187 dfs_c(now,now); 188 for (RG i=g[now];i;i=e[i].next) 189 { 190 RG v=e[i].y; 191 if (bj[v]) continue; 192 solve(v,now); 193 } 194 RG si=c[now].size(); 195 sort(c[now].begin(),c[now].end(),cmp); 196 c[now][0].qz=c[now][0].dis; 197 c[now][0].qz_=c[now][0].dis_; 198 for (RG i=1;i<si;i++) 199 { 200 c[now][i].qz=c[now][i-1].qz+c[now][i].dis; 201 c[now][i].qz_=c[now][i-1].qz_+c[now][i].dis_; 202 } 203 } 204 205 void read() {RG x,y; x=getint(),y=getint(); L=min((x+ans)%A,(y+ans)%A); R=max((x+ans)%A,(y+ans)%A);} 206 207 inline llg erfen(RG x, RG V,RG dis_,bool pd) 208 { 209 RG l=0,r=c[x].size()-1,mid,wz=-1; 210 while (l<=r) 211 { 212 mid=(l+r)>>1; 213 if (c[x][mid].age<=V) {wz=mid; l=mid+1;}else{r=mid-1;} 214 } 215 if (wz==-1) return 0; 216 if (pd) return c[x][wz].qz+(dis_-find_dis(dad[x],o))*(wz+1)-c[x][wz].qz_; 217 else return c[x][wz].qz_+(wz+1)*(find_dis(dad[x],o)-dis_)-c[x][wz].qz; 218 } 219 220 inline llg erfen_(RG x,RG V) 221 { 222 RG l=0,r=c[x].size()-1,mid,wz=-1; 223 while (l<=r) 224 { 225 mid=(l+r)>>1; 226 if (c[x][mid].age<=V) {wz=mid; l=mid+1;}else{r=mid-1;} 227 } 228 if (wz==-1) return 0; 229 return (wz+1)*find_dis(dad[x],o)+c[x][wz].qz_; 230 } 231 232 inline void find(register llg x) 233 { 234 RG dis_=find_dis(x,o); 235 // llg sum=erfen(x,R,dis_)-erfen(x,L-1,dis_); 236 // llg dec=erfen_(x,R)-erfen_(x,L-1); 237 ans+=erfen(x,R,dis_,1)+erfen(x,L-1,dis_,0); 238 // ans+=sum-dec; 239 if (dad[x]!=0) find(dad[x]); 240 } 241 242 llg dg(llg x) 243 { 244 if (dad[x]!=0) return dg(dad[x])+1; 245 else return 1; 246 } 247 248 int main() 249 { 250 yyj("shop"); 251 init(); 252 solve(1,0); 253 /* for (llg i=1;i<=n;i++) 254 { 255 maxl=max(maxl,dg(i)); 256 } 257 cout<<maxl; return 0;*/ 258 while (Q--) 259 { 260 o=getint(); 261 read(); 262 ans=0; 263 find(o); 264 write(ans); 265 } 266 // cout<<clock(); 267 return 0; 268 }
本文作者:xrdog
作者博客:http://www.cnblogs.com/Dragon-Light/
转载请注明出处,侵权必究,保留最终解释权!