动态点分治

[ZJOI2015]幻想乡战略游戏

给一棵树,边有边权,点有点权(初始为0),每次修改一个点的点权,并询问带权重心u使得所有点点权乘以到u的距离的和最小,输出这个最小值.

保证每个点度数不超过20

考虑对于一颗没有修改的树如何求带权重心

对于一条边(u,v),设u为v的父亲,sum[x]表示以x为根的子树的点权和,totsum表示整棵树的点权和.

从u到v,答案减小val(u,v)*sum[v],增加val(u,v)*totsum-sum[v]

那么v比u优当且仅当sum[v]>totsum-sum[v]即2*sum[v]>totsum

(等于的情况再往u的儿子移动sum只会变小,不可能变得更优了,所以直接把v作为答案即可)

所以从根出发一直往这样儿子走即可找到答案.当然这样复杂度会很高,,

这个时候就容易想到点分治了,因为若往分治儿子走最多只用走log次诶

每个点维护它管辖的所有点的点权和sum[x],对于每个点u,它管辖的区域内,和它的分治父亲v相连的点记为w

每次从根出发在分治树上找答案,当2*sum[u]>=tot时,从v走到u,同时将w到u的分治树上路径上的所有点的sum加上sum[v]-sum[u](找到答案回溯时要把sum还原)

这样就能在两个log内找到重心

知道点之后如何维护答案呢,再对每个点x维护g[x]表示它分治子树中所有点以它为根的答案和gtf[x]表示它分治子树中所有点以它分治父亲为根的答案

那么沿着分治父亲跳的时候,答案加上它父亲的g减去它的gtf加上它父亲的sum减去它的sum乘它到它父亲的距离

求距离时需要用到lca,最好用st表O(1)查询.lca都写挂的我..

  1 // luogu-judger-enable-o2
  2 //Achen
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<vector>
  8 #include<cstdio>
  9 #include<queue>
 10 #include<cmath>
 11 #include<set>
 12 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 14 const int N=1e5+7;
 15 typedef long long LL; 
 16 typedef double db;
 17 using namespace std;
 18 int n,Q,RT;
 19 
 20 template<typename T> void read(T &x) {
 21     char ch=getchar(); x=0; T f=1;
 22     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 23     if(ch=='-') f=-1,ch=getchar();
 24     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 25 }
 26 
 27 int ecnt,fir[N],nxt[N<<1],to[N<<1],val[N<<1];
 28 void add(int u,int v,int w) {
 29     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
 30     nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
 31 }
 32 
 33 int dfs_clock,dfn[N],tid[N<<1],R[N],H[N];
 34 void dfs(int x,int fa) {
 35     dfn[x]=++dfs_clock;
 36     tid[dfn[x]]=x;
 37     R[x]=R[fa]+1;
 38     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
 39         H[to[i]]=H[x]+val[i];
 40         dfs(to[i],x);
 41         ++dfs_clock;
 42         tid[dfs_clock]=x;
 43     }
 44 }
 45 
 46 int st[N<<1][20];
 47 void pre_RMQ() {
 48     For(i,1,dfs_clock-1) st[i][0]=(R[tid[i]]<R[tid[i+1]])?tid[i]:tid[i+1];
 49     For(j,1,17) 
 50         For(i,1,dfs_clock) if(i+(1<<j)<=dfs_clock) 
 51             st[i][j]=R[st[i][j-1]]<R[st[i+(1<<j-1)][j-1]]?st[i][j-1]:st[i+(1<<j-1)][j-1];
 52 }
 53 
 54 int lca(int x,int y) {
 55     if(x==y) return x;
 56     x=dfn[x]; y=dfn[y];
 57     if(x>y) swap(x,y);
 58     int k=0; while(x+(1<<k)<=y) k++; if(k) k--;
 59     return R[st[x][k]]<R[st[y-(1<<k)][k]]?st[x][k]:st[y-(1<<k)][k];
 60 }
 61 
 62 int d[N];
 63 LL f[N],g[N],gtf[N];//f:sum of d /g:ans /gtf:ans to f  
 64 
 65 int sz[N],mxson[N];
 66 int rt,vis[N],F[N],sznow,wtf[N];
 67 void dfs2(int x,int fa) {
 68     sz[x]=1;
 69     for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa) {
 70         dfs2(to[i],x);
 71         sz[x]+=sz[to[i]];
 72     }
 73 }
 74 
 75 void get_rt(int x,int fa) {
 76     sz[x]=mxson[x]=1;
 77     for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa) {
 78         get_rt(to[i],x);
 79         sz[x]+=sz[to[i]];
 80         mxson[x]=max(mxson[x],sz[to[i]]);
 81     }
 82     mxson[x]=max(mxson[x],sznow-sz[x]);
 83     if(!rt||mxson[x]<mxson[rt]) rt=x;
 84 }
 85 
 86 int ec,fi[N],nx[N],tt[N];
 87 void ADD(int u,int v) {
 88     nx[++ec]=fi[u]; fi[u]=ec; tt[ec]=v;
 89 }
 90 
 91 void solve(int x,int FA) {
 92     F[x]=FA;
 93     if(FA) ADD(FA,x);
 94     vis[x]=1;
 95     dfs2(x,0);
 96     for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]) {
 97         rt=0; sznow=sz[to[i]];
 98         get_rt(to[i],x); 
 99         wtf[rt]=to[i]; solve(rt,x);
100     }
101 }
102 
103 LL get_dis(int x,int y) { return H[x]+H[y]-2LL*H[lca(x,y)]; }
104 
105 void change(int x,int y,int v) {
106     f[x]+=v;
107     g[x]+=(LL)v*get_dis(x,y);
108     gtf[x]+=(LL)v*get_dis(F[x],y);
109     if(F[x]) change(F[x],y,v);
110 }
111 
112 int find(int x) {
113     for(int i=fi[x];i;i=nx[i]) {
114         int y=tt[i];
115         if(f[y]*2>f[x]) {
116             int z=wtf[y];
117             LL w=f[x]-f[y];
118             for(;;) {
119                 f[z]+=w;
120                 if(z==y) break;
121                 z=F[z];
122             }
123             int rs=find(y);
124             z=wtf[y];
125             for(;;) {
126                 f[z]-=w;
127                 if(z==y) break;
128                 z=F[z];
129             }
130             return rs;
131         }
132     } return x;
133 }
134 
135 LL qry(int x) {
136     LL rs=0; int tp=x;
137     rs+=g[x];
138     int pr=x; x=F[x];
139     while(x) {
140         rs+=g[x]-gtf[pr]+(LL)(f[x]-f[pr])*get_dis(x,tp);
141         pr=x; x=F[x];
142     }
143     return rs;
144 }
145 
146 //#define DEBUG
147 int main() {
148 #ifdef DEBUG
149     freopen("std.in","r",stdin);
150     //freopen(".out","w",stdout);
151 #endif
152     read(n); read(Q);
153     For(i,1,n-1) {
154         int x,y,z;
155         read(x); read(y); read(z);
156         add(x,y,z);
157     }
158     dfs(1,0);
159     pre_RMQ();
160     rt=0; sznow=n;
161     get_rt(1,0); 
162     RT=rt;
163     solve(rt,0);
164     while(Q--) {
165         int x,y;
166         read(x); read(y);
167         d[x]+=y;
168         change(x,x,y);
169         x=find(RT);
170         printf("%lld
",qry(x));
171     }
172     return 0;
173 }
174 /*
175 10 5
176 1 2 1
177 2 3 1
178 2 4 1
179 1 5 1
180 2 6 1
181 2 7 1
182 5 8 1
183 7 9 1
184 1 10 1
185 3 1
186 2 1
187 8 1
188 3 1
189 4 1
190 */
View Code

 

bzoj3730: 震波

一棵树,有点权,边权均为1.支持修改某个点的点权和查询距离某个点不超过k的所有点的点权和.

点分树建出来,每个点维护它管辖范围内所有点按距离排序的点权和,用线段树或者数状数组(其实我一开始想的是用treap..)

每个点再开一个数状数组维护它管辖范围内所有点按与父亲的距离排序的点权和

数状数组要把每一层开在一起,才不会炸空间

查询的时候沿着父亲跑,若查询点到当前点的距离dis<=k,ans加上距当前点小于等于k-dis的距离和,减去上一个点中据父亲小于等于k-dis的距离和

需要注意当dis>k时并不能跳出,应该继续沿着父亲跑.

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 13 const int N=200007;
 14 typedef long long LL; 
 15 typedef double db;
 16 using namespace std;
 17 int n,m,v[N];
 18 
 19 template<typename T> void read(T &x) {
 20     char ch=getchar(); x=0; T f=1;
 21     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 22     if(ch=='-') f=-1,ch=getchar();
 23     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 24 }
 25 
 26 int sum[2][30][N],st[N],ed[N];
 27 void add(int o,int id,int x,int v) {
 28     for(int i=x;i<=n;i+=(i&(-i))) 
 29         sum[o][id][i]+=v;
 30 }
 31 
 32 int qry(int o,int id,int x) {
 33     int rs=0;
 34     if(x<=0) return rs;
 35     for(int i=x;i;i-=(i&(-i))) 
 36         rs+=sum[o][id][i];
 37     return rs;
 38 }
 39 
 40 int ecnt,fir[N],nxt[N<<1],to[N<<1];
 41 void ADD(int u,int v) {
 42     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
 43     nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
 44 }
 45 
 46 int dfs_clock,dfn[N],tid[N<<1],R[N];
 47 void dfs(int x,int fa) {
 48     dfn[x]=++dfs_clock;
 49     tid[dfn[x]]=x;
 50     R[x]=R[fa]+1;
 51     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
 52         dfs(to[i],x);
 53         ++dfs_clock;
 54         tid[dfs_clock]=x;
 55     }
 56 }
 57 
 58 int ST[N<<1][25];
 59 void pre_RMQ() {
 60     For(i,1,dfs_clock-1) ST[i][0]=(R[tid[i]]<R[tid[i+1]])?tid[i]:tid[i+1];
 61     For(j,1,20) 
 62         For(i,1,dfs_clock) if(i+(1<<j)<=dfs_clock) 
 63             ST[i][j]=R[ST[i][j-1]]<R[ST[i+(1<<j-1)][j-1]]?ST[i][j-1]:ST[i+(1<<j-1)][j-1];
 64 }
 65 
 66 int lca(int x,int y) {
 67     if(x==y) return x;
 68     x=dfn[x]; y=dfn[y];
 69     if(x>y) swap(x,y);
 70     int k=0; while(x+(1<<k)<=y) k++; if(k) k--;
 71     return R[ST[x][k]]<R[ST[y-(1<<k)][k]]?ST[x][k]:ST[y-(1<<k)][k];
 72 }
 73 
 74 int get_dis(int x,int y) { return R[x]+R[y]-2LL*R[lca(x,y)]; }
 75 
 76 int rt,sznow,vis[N],sz[N],mxson[N];
 77 void get_rt(int x,int fa) {
 78     sz[x]=mxson[x]=1;
 79     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa&&!vis[to[i]]) {
 80         get_rt(to[i],x);
 81         sz[x]+=sz[to[i]];
 82         mxson[x]=max(mxson[x],sz[to[i]]);
 83     }
 84     mxson[x]=max(mxson[x],sznow-sz[x]);
 85     if(!rt||mxson[rt]>mxson[x]) rt=x;
 86 }
 87 
 88 int len[30];
 89 int F[N],D[N];
 90 void dfs2(int x,int fa,int rt) {
 91     sz[x]=1;
 92     add(0,D[rt],st[rt]+get_dis(x,rt)+1,v[x]);
 93     if(F[rt]) add(1,D[rt],st[rt]+get_dis(x,F[rt]),v[x]);
 94     for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa) {
 95         dfs2(to[i],x,rt);
 96         sz[x]+=sz[to[i]];
 97     }
 98 }
 99 
100 void solve(int x,int FA,int dep) {
101     F[x]=FA;
102     vis[x]=1;
103     D[x]=dep;
104     dfs2(x,0,x);
105     for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]) {
106         rt=0; sznow=sz[to[i]];
107         get_rt(to[i],0); 
108         st[rt]=len[dep+1];
109         len[dep+1]+=sznow;
110         solve(rt,x,dep+1);
111     }
112 }
113 
114 void change(int x,int y,int V) {
115     while(x) {
116         add(0,D[x],st[x]+get_dis(x,y)+1,V);
117         if(F[x]) add(1,D[x],st[x]+get_dis(F[x],y),V);
118         x=F[x];
119     }
120 }
121 
122 int ans;
123 int get_ans(int x,int k) {
124     int rs=qry(0,D[x],min(ed[x],st[x]+k+1))-qry(0,D[x],st[x]);
125     int tp=x,pr=x; x=F[x];
126     while(x) {
127         int kk=get_dis(x,tp); kk=k-kk;
128         if(kk>=0) rs-=qry(1,D[pr],min(ed[pr],st[pr]+kk))-qry(1,D[pr],st[pr]);
129         if(kk>=0) rs+=qry(0,D[x],min(ed[x],st[x]+kk+1))-qry(0,D[x],st[x]);
130         pr=x; x=F[x];
131     }
132     return rs;    
133 }
134 
135 //#define DEBUG
136 int main() {
137 #ifdef DEBUG
138     freopen("std.in","r",stdin);
139     //freopen(".out","w",stdout);
140 #endif
141     read(n); read(m);
142     For(i,1,n) read(v[i]);
143     For(i,2,n) {
144         int x,y;
145         read(x); read(y);
146         ADD(x,y);
147     }
148     dfs(1,0);
149     pre_RMQ();
150     sznow=n; rt=0;
151     get_rt(1,0);
152     solve(rt,0,1);
153     For(i,1,n) ed[i]=st[i]+sz[i];
154     For(ti,1,m) {
155         int o,x,y,k;
156         read(o);
157         if(o==0) {
158             read(x); read(k);
159             x^=ans; k^=ans;
160             ans=get_ans(x,k);
161             printf("%d
",ans);
162         }
163         else {
164             read(x); read(y);
165             x^=ans; y^=ans;
166             change(x,x,y-v[x]);
167             v[x]=y;
168         }
169     }
170     return 0;
171 }
172 /*
173 8 1
174 1 10 100 1000 10000 100000 1000000 10000000
175 1 2
176 1 3
177 2 4
178 2 5
179 3 6
180 3 7
181 3 8
182 0 3 1
183 */
View Code

码力实在弱得令人发指,各种bug....之前看到有人说码力弱本质是题没有想清楚.即使努力先想清楚再写,看了代码一遍又一遍也没有发现问题,只有调试才能发现自己还是有些地方没有想清楚..

 5.7upd

4372: 烁烁的游戏

现在写这题感觉是模板呀,和震波差不多只是因为最大都到n所以用动态开点的线段树维护.

每个点维护它分治树中都子树中的加都操作如果到它这里还可以继续延伸都话,按还可以延伸都长度排序,线段树维护权值和

每个点分治子树对它都贡献在加的时候直接算到点上,剩下都就是沿着父亲跑,然后套路的每次是父亲中的减去在它子树中的.

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 14 const int N=1e5+7;
 15 typedef long long LL; 
 16 typedef double db;
 17 using namespace std;
 18 int n,m;
 19 char o[10];
 20 
 21 template<typename T> void read(T &x) {
 22     char ch=getchar(); x=0; T f=1;
 23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 24     if(ch=='-') f=-1,ch=getchar();
 25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 26 }
 27 
 28 int ecnt,fir[N],nxt[N<<1],to[N<<1];
 29 void add(int u,int v) {
 30     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
 31     nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
 32 }
 33 
 34 int dfn[N<<1],tid[N<<1],R[N<<1],dfs_clock;
 35 void dfs(int x,int fa) {
 36     R[x]=R[fa]+1;
 37     dfn[x]=++dfs_clock;
 38     tid[dfn[x]]=x;
 39     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
 40         dfs(to[i],x);
 41         tid[++dfs_clock]=x;
 42     }
 43 }
 44 
 45 int st[N<<1][20];
 46 void pre_st() {
 47     For(i,1,dfs_clock-1) st[i][0]=R[tid[i]]<R[tid[i+1]]?tid[i]:tid[i+1];
 48     For(j,1,17) For(i,1,dfs_clock) if(i+(1<<j)<=dfs_clock) 
 49         st[i][j]=R[st[i][j-1]]<R[st[i+(1<<j-1)][j-1]]?st[i][j-1]:st[i+(1<<j-1)][j-1];
 50 }
 51 
 52 int lca(int x,int y) {
 53     if(x==y) return x;
 54     x=dfn[x]; y=dfn[y]; 
 55     if(x>y) swap(x,y);
 56     int k;
 57     for(k=0;x+(1<<k)<=y;k++); if(k) k--;
 58     return R[st[x][k]]<R[st[y-(1<<k)][k]]?st[x][k]:st[y-(1<<k)][k];
 59 }
 60 
 61 int dis(int x,int y) { return R[x]+R[y]-2*R[lca(x,y)]; }
 62 
 63 int rt,f[N],sz[N],mson[N],vis[N],sznow;
 64 void get_root(int x,int fa) {
 65     sz[x]=mson[x]=1;
 66     for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa) {
 67         get_root(to[i],x);
 68         sz[x]+=sz[to[i]];
 69         mson[x]=max(mson[x],sz[to[i]]);
 70     }
 71     mson[x]=max(mson[x],sznow-sz[x]);
 72     if(!rt||mson[x]<mson[rt]) rt=x;
 73 }
 74 
 75 void dfs2(int x,int fa) { 
 76     sz[x]=1; 
 77     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa&&!vis[to[i]]) {
 78         dfs2(to[i],x); sz[x]+=sz[to[i]];
 79     }
 80 }
 81 
 82 void solve(int x,int FA) {
 83     f[x]=FA;
 84     vis[x]=1;
 85     dfs2(x,0);
 86     for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]]) {
 87         rt=0; sznow=sz[to[i]];
 88         get_root(to[i],0); solve(rt,x);
 89     }
 90 }
 91 
 92 int rt1[N],rt2[N],sg[N*200],ch[N*200][2],tot;
 93 #define lc ch[x][0]
 94 #define rc ch[x][1]
 95 #define mid ((l+r)>>1)
 96 void update(int &x,int l,int r,int pos,int v) {
 97     if(!x) x=++tot;
 98     if(l==r) { sg[x]+=v; return; }
 99     if(pos<=mid) update(lc,l,mid,pos,v);
100     else update(rc,mid+1,r,pos,v);
101     sg[x]=sg[lc]+sg[rc];
102 }
103 
104 int qry(int x,int l,int r,int ql,int qr) {
105     if(!x) return 0;
106     if(l>=ql&&r<=qr) return sg[x];
107     if(qr<=mid) return qry(lc,l,mid,ql,qr);
108     if(ql>mid) return qry(rc,mid+1,r,ql,qr);
109     return qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr);
110 }
111 
112 int Ans[N];
113 void change(int x,int d,int w) {
114     d=min(d,n); int z=x;
115     while(x) {
116         int d1=dis(x,z);
117         if(d1<=d) {
118             Ans[x]+=w;
119             if(d-d1>0) update(rt1[x],1,n,d-d1,w);
120         }
121         if(f[x]) {
122             int d2=dis(f[x],z);
123             if(d-d2>0) update(rt2[x],1,n,d-d2,w);
124         }
125         x=f[x];
126     }
127 }
128 
129 int qry(int x) {
130     int rs=Ans[x],z=x;
131     while(f[x]) {
132         int d=dis(z,f[x]);
133         rs+=qry(rt1[f[x]],1,n,d,n);
134         rs-=qry(rt2[x],1,n,d,n);
135         x=f[x];
136     }
137     return rs;
138 }
139 
140 //#define DEBUG
141 int main() {
142 #ifdef DEBUG
143     freopen("4372.in","r",stdin);
144     freopen("4372.out","w",stdout);
145 #endif
146     read(n); read(m);
147     For(i,1,n-1) {
148         int u,v;
149         read(u); read(v); add(u,v);
150     }
151     dfs(1,0);
152     pre_st();
153     rt=0; sznow=n;
154     get_root(1,0);
155     solve(rt,0);
156     int tptot=0;
157     while(m--) {
158         scanf("%s",o);
159         int x,d,w;
160         if(tot>=10000690) {
161             int debug=1;
162         }
163         if(o[0]=='Q') {
164             tptot++;
165             if(tptot==46217) {
166                 int debug=1;
167             }
168             read(x);
169             printf("%d
",qry(x));
170         }
171         else {
172             read(x); read(d); read(w);
173             change(x,d,w);
174         }
175     }
176     //printf("%d
",tot);
177     return 0;
178 }
View Code

 

原文地址:https://www.cnblogs.com/Achenchen/p/8877969.html