ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[uoj576]服务调度

2021-01-07 08:33:03  阅读:168  来源: 互联网

标签:uoj576 服务 int 调度 deep fa lca return dis


先考虑一个子问题:仅有一个询问且无修改

对每一种颜色的贡献分类讨论,结论:最远的点一定这些点集中(任意一组)最远点对中的两个点(选择较远的一个)

证明:设$dis(x,y)$为$x$到$y$的距离,$deep_{x}$表示以$k$为根时$x$的深度

假设这个点集中最远点为$(x,y)$,而最深的点为$z$,且$deep_{z}$严格大于$deep_{x}$和$deep_{y}$

一个显然的性质:$deep_{lca(x,y)}\le deep_{x},deep_{y}$

考虑$w=lca(x,y,z)$,若$z=w$与$deep_{z}>deep_{x},deep_{y}$矛盾,因此假设$z$在$w$的某个儿子$w_{z}$中

当若$x$和$y$都在$w_{z}$的子树中显然$lca(x,y,z)$可以为$w_{z}$,因此必然存在一个点在其子树外,不妨设为是$x$,则$lca(x,z)=w$,必然有$deep_{w}\le deep_{lca(x,y)}$

考虑此时$dis(x,z)$与$dis(x,y)$,通过lca的形式展开,由于$deep_{z}>deep_{y}$且$deep_{w}\le deep_{lca(x,y)}$,因此$dis(x,z)>dis(x,y)$,与$(x,y)$为最远点对矛盾

通过合并的方式(即不断插入一个点,三个点两两求$dis$)求出每一个点集的最远点对$(x,y)$,这一部分可以做到$o(n\log_{2}n)$

进一步的,不妨假设$deep_{x}\ge deep_{y}$(此时的$deep$为以1为根),通过倍增找到$z$满足$z$在$x$到$lca(x,y)$的路径上且$dis(x,z)<\lceil\frac{dis(x,y)}{2}\rceil$中$dis(x,z)$最大,那么$k$满足$dis(k,y)>dis(k,x)$当且仅当$k$在$z$子树中

特别的,当$x=y$时令$z=x$,这是为了方便处理,证明比较显然,这里就省略了

接下来,考虑对答案的贡献,分为两部分:

1.$z$的子树中,点$k$的答案加上$deep_{y}+deep_{k}-2depp_{lca(x,y)}$,首尾两个式子都为常数,线段树+dfs序即可,$deep_{k}$通过打“区间加点深度”的标记,再维护区间内所有点深度和即可处理

2.$z$的子树外,考虑$deep_{x}+deep_{k}-2deep_{lca(x,k)}$,前两个式子与上面处理方式相同,考虑第三个式子——

再建一棵线段树,将$fa_{z}$到根的路径打上“减2倍其到父亲的边权”,那么一个点所需要减的就是其到根路径上所有点的和,同时对$z$的子树内部没有影响,因此应对$z$的子树区间加$fa_{z}$的深度

这个考虑在询问时处理,假设询问$k$的子树,对于$k$到根路径上的所有点都会被减小$k$子树大小次,之后对于$k$子树内部的点会被减小子树大小次

分别维护这个值以及这个值乘对应子树大小的两颗线段树就可以处理了,另外链修改需要树链剖分,总复杂度为$o(n\log^{2}n)$

(注意,这样两颗线段树是独立的,也就是对两边的贡献用不同的方式计算)

对于修改,可以看作在某种颜色中插入/删除一个点,对于插入同样直径合并(之后重新修改),删除可以用线段树来做,同样利用直径合并的性质就可以做了(注意修改完直径后都要重新计算贡献)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 200005
  4 #define ll long long
  5 #define L (k<<1)
  6 #define R (L+1)
  7 #define mid (l+r>>1)
  8 #define pii pair<int,int>
  9 #define fi first
 10 #define se second
 11 struct ji{
 12     int nex,to,len;
 13 }edge[N];
 14 int E,n,m,t,x,p,a[N],head[N],d1[N],d2[N],sz[N],son[N],dfn[N],inv_dfn[N],top[N],fa[N][21];
 15 int V,pos[N],rt[N],ls[N*40],rs[N*40];
 16 vector<int>v[N];
 17 pii fd[N*40];
 18 ll val[4][N<<2],tag[4][N<<2],f[4][N<<2];
 19 void add(int x,int y,int z){
 20     edge[E].nex=head[x];
 21     edge[E].to=y;
 22     edge[E].len=z;
 23     head[x]=E++;
 24 }
 25 void dfs1(int k,int s1,int s2){
 26     d1[k]=s1;
 27     d2[k]=s2;
 28     sz[k]=1;
 29     for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
 30     for(int i=head[k];i!=-1;i=edge[i].nex)
 31         if (edge[i].to!=fa[k][0]){
 32             dfs1(edge[i].to,s1+1,s2+edge[i].len);
 33             sz[k]+=sz[edge[i].to];
 34             if ((!son[k])||(sz[son[k]]<sz[edge[i].to]))son[k]=edge[i].to;
 35         }
 36 }
 37 void dfs2(int k,int t){
 38     dfn[k]=++x;
 39     inv_dfn[x]=k;
 40     top[k]=t;
 41     if (son[k])dfs2(son[k],t);
 42     for(int i=head[k];i!=-1;i=edge[i].nex){
 43         int u=edge[i].to;
 44         if ((u!=fa[k][0])&&(u!=son[k]))dfs2(u,u);
 45     }
 46 }
 47 int lca(int x,int y){
 48     if (d1[x]<d1[y])swap(x,y);
 49     for(int i=20;i>=0;i--)
 50         if (d1[fa[x][i]]>=d1[y])x=fa[x][i];
 51     if (x==y)return x;
 52     for(int i=20;i>=0;i--)
 53         if (fa[x][i]!=fa[y][i]){
 54             x=fa[x][i];
 55             y=fa[y][i];
 56         }
 57     return fa[x][0];
 58 }
 59 int dis(int x,int y){
 60     if ((!x)||(!y))return 0;
 61     return d2[x]+d2[y]-2*d2[lca(x,y)];
 62 }
 63 pii merge(pii x,pii y){
 64     int d=0,a[5];
 65     pair<int,int>ans=make_pair(0,0);
 66     a[0]=0;
 67     if (x.fi)a[++a[0]]=x.fi;
 68     if (x.se)a[++a[0]]=x.se;
 69     if (y.fi)a[++a[0]]=y.fi;
 70     if (y.se)a[++a[0]]=y.se;
 71     if (a[0]==1)return make_pair(a[1],0);
 72     for(int i=1;i<=a[0];i++)
 73         for(int j=i+1;j<=a[0];j++){
 74             int dd=dis(a[i],a[j]);
 75             if (dd>d){
 76                 d=dd;
 77                 ans=make_pair(a[i],a[j]);
 78             }
 79         }
 80     return ans;
 81 }
 82 void update(int &k,int l,int r,int x,int y){
 83     if (!k)k=++V;
 84     if (l==r){
 85         fd[k]=make_pair(y,0);
 86         return;
 87     }
 88     if (x<=mid)update(ls[k],l,mid,x,y);
 89     else update(rs[k],mid+1,r,x,y);
 90     fd[k]=merge(fd[ls[k]],fd[rs[k]]);
 91 }
 92 void up(int k){
 93     for(int i=0;i<4;i++)f[i][k]=f[i][L]+f[i][R];
 94 }
 95 void upd(int p,int k,int x){
 96     tag[p][k]+=x;
 97     f[p][k]+=x*val[p][k];
 98 }
 99 void down(int k){
100     for(int i=0;i<4;i++)
101         if (tag[i][k]){
102             upd(i,L,tag[i][k]);
103             upd(i,R,tag[i][k]);
104             tag[i][k]=0;
105         }
106 }
107 void build(int k,int l,int r){
108     if (l==r){
109         x=inv_dfn[l];
110         val[0][k]=1;
111         val[1][k]=d2[x];
112         if (x==1)val[2][k]=0;
113         else val[2][k]=d2[x]-d2[fa[x][0]];
114         val[3][k]=val[2][k]*sz[x];
115         return;
116     }
117     build(L,l,mid);
118     build(R,mid+1,r);
119     for(int i=0;i<4;i++)val[i][k]=val[i][L]+val[i][R];
120 }
121 void update(int p,int k,int l,int r,int x,int y,int z){
122     if ((l>y)||(x>r))return;
123     if ((x<=l)&&(r<=y)){
124         upd(p,k,z);
125         return;
126     }
127     down(k);
128     update(p,L,l,mid,x,y,z);
129     update(p,R,mid+1,r,x,y,z);
130     up(k);
131 }
132 ll query(int p,int k,int l,int r,int x,int y){
133     if ((l>y)||(x>r))return 0;
134     if ((x<=l)&&(r<=y))return f[p][k];
135     down(k);
136     return query(p,L,l,mid,x,y)+query(p,R,mid+1,r,x,y);
137 }
138 void calc(int k,int p){
139     int x=fd[rt[k]].fi,y=fd[rt[k]].se;
140     if (!x)return;
141     int z;
142     if (!y)z=y=x;
143     else{
144         if (d2[x]<d2[y])swap(x,y);
145         z=x;
146         int d=(dis(x,y)+1)/2;
147         for(int i=20;i>=0;i--)
148             if (d2[x]-d2[fa[z][i]]<d)z=fa[z][i];
149     }
150     update(0,1,1,n,dfn[z],dfn[z]+sz[z]-1,p*(d2[y]-2*d2[lca(x,y)]));
151     update(0,1,1,n,1,dfn[z]-1,p*d2[x]);
152     update(0,1,1,n,dfn[z]+sz[z],n,p*d2[x]);
153     update(1,1,1,n,1,n,p);
154     update(0,1,1,n,dfn[z],dfn[z]+sz[z]-1,2*p*d2[fa[z][0]]);
155     z=fa[z][0];
156     while (z>1){
157         update(2,1,1,n,dfn[top[z]],dfn[z],-2*p);
158         update(3,1,1,n,dfn[top[z]],dfn[z],-2*p);
159         z=fa[top[z]][0];
160     }
161 }
162 ll query(int k){
163     ll ans=0;
164     for(int i=0;i<4;i++)
165         if (i!=2)ans+=query(i,1,1,n,dfn[k],dfn[k]+sz[k]-1);
166     int x=sz[k];
167     k=fa[k][0];
168     while (k>1){
169         ans+=x*query(2,1,1,n,dfn[top[k]],dfn[k]);
170         k=fa[top[k]][0];
171     }
172     return ans;
173 }
174 int main(){
175     scanf("%d%d%d",&n,&t,&m);
176     for(int i=1;i<=n;i++){
177         scanf("%d",&a[i]);
178         v[a[i]].push_back(i);
179         pos[i]=v[a[i]].size();
180     }
181     memset(head,-1,sizeof(head));
182     fa[1][0]=1;
183     for(int i=2;i<=n;i++)scanf("%d",&fa[i][0]);
184     for(int i=2;i<=n;i++){
185         scanf("%d",&x);
186         add(fa[i][0],i,x);
187     }
188     dfs1(1,0,0);
189     x=0;
190     dfs2(1,1);
191     build(1,1,n);
192     for(int i=1;i<=n;i++)update(rt[a[i]],1,n+m,pos[i],i);
193     for(int i=1;i<=t;i++)calc(i,1);
194     for(int i=1;i<=m;i++){
195         scanf("%d%d",&p,&x);
196         if (p==2)printf("%lld\n",query(x));
197         else{
198             calc(a[x],-1);
199             update(rt[a[x]],1,n+m,pos[x],0);
200             calc(a[x],1);
201             scanf("%d",&a[x]);
202             calc(a[x],-1);
203             v[a[x]].push_back(x);
204             pos[x]=v[a[x]].size();
205             update(rt[a[x]],1,n+m,pos[x],x);
206             calc(a[x],1);
207         }
208     }
209 }
View Code

 

标签:uoj576,服务,int,调度,deep,fa,lca,return,dis
来源: https://www.cnblogs.com/PYWBKTDA/p/14244439.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有