BZOJ3052: [wc2013]糖果公园
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3052
题解:700T刷道有分量的题。。。
其实不加修改操作和苹果树是一样的。加上之后我们可以对每个询问加上一维时间,然后balabala。
为什么块要取n^2/3?
VFleaKing:
取B = n ^ (2 / 3),设 nBlo为块的个数,用bloNum[v]来代表v所在块的编号。(block number)
则同一个块内任意两结点的距离为O(n ^ (2 / 3))的。
按照之前我说的方式对询问进行排序,按顺序作答。
注意到(bloNum[curV], bloNum[curU])一共有nBlo ^ 2个取值。
那么如果移动一次,curV还在原来的块,curU还在原来的块,这种移动的总时间复杂度是O(nBlo ^ 2 * q)的。(因为curTi还要移动)
如果移动一次,curV不在原来的块,curU不在原来的块,这种移动发生的次数最多为 nBlo ^ 2。因为我是排好序的了嘛,相同块的是放在一起的。而这种移动发生一次最坏是O(n + n + q) = O(n)。(n、q是同阶的)
所以这样回答所有询问,时间复杂度就是O(nBlo ^ 2 * n)的。
由于B = n ^ (2 / 3),块的大小介于[B, 3 * B]之间。
则nBlo = O(n ^ (1 / 3))
则时间复杂度为O(n ^ (5 / 3))。
1A简直不能更爽。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 100000+5 14 #define maxm 100000+5 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 23 #define mod 1000000007 24 using namespace std; 25 inline int read() 26 { 27 int x=0,f=1;char ch=getchar(); 28 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 29 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 30 return x*f; 31 } 32 int n,m,k,tot,cnt,f[maxn][18],bin[20],dfn[maxn],ti,belong[maxn],top,sta[maxn]; 33 int l,r,t,s[maxn],v[maxn],w[maxn],dep[maxn],head[maxn],size,c[maxn],pre[maxn]; 34 bool vis[maxn]; 35 ll ret,ans[maxn]; 36 struct rec{int x,y,id,t;}a[maxn],b[maxn]; 37 struct edge{int go,next;}e[2*maxn]; 38 inline void add(int x,int y) 39 { 40 e[++tot]=(edge){y,head[x]};head[x]=tot; 41 e[++tot]=(edge){x,head[y]};head[y]=tot; 42 } 43 inline void dfs(int x) 44 { 45 dfn[x]=++ti;int tmp=top; 46 for1(i,17)if(bin[i]<=dep[x])f[x][i]=f[f[x][i-1]][i-1];else break; 47 for4(i,x)if(y!=f[x][0]) 48 { 49 dep[y]=dep[x]+1;f[y][0]=x;dfs(y); 50 if(top-tmp>=size) 51 { 52 ++cnt; 53 while(top!=tmp)belong[sta[top--]]=cnt; 54 } 55 } 56 sta[++top]=x; 57 } 58 inline int lca(int x,int y) 59 { 60 if(dep[x]<dep[y])swap(x,y); 61 int t=dep[x]-dep[y]; 62 for0(i,17)if(t&bin[i])x=f[x][i]; 63 if(x==y)return x; 64 for3(i,17,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; 65 return f[x][0]; 66 } 67 inline void change(int x) 68 { 69 if(vis[x]){ret-=(ll)w[s[c[x]]]*v[c[x]];s[c[x]]--;} 70 else {s[c[x]]++;ret+=(ll)w[s[c[x]]]*v[c[x]];} 71 vis[x]^=1; 72 } 73 inline void work(int x,int y) 74 { 75 while(x!=y) 76 { 77 if(dep[x]<dep[y])swap(x,y); 78 change(x); 79 x=f[x][0]; 80 } 81 } 82 inline void color(int x,int y) 83 { 84 if(!vis[x])c[x]=y; 85 else 86 { 87 change(x); 88 c[x]=y; 89 change(x); 90 } 91 } 92 inline bool cmp(rec a,rec b){return belong[a.x]==belong[b.x]?dfn[a.y]<dfn[b.y]:belong[a.x]<belong[b.x];} 93 int main() 94 { 95 freopen("input.txt","r",stdin); 96 freopen("output.txt","w",stdout); 97 n=read();m=read();k=read(); 98 bin[0]=1;for1(i,17)bin[i]=bin[i-1]<<1; 99 for1(i,m)v[i]=read(); 100 for1(i,n)w[i]=read(); 101 for1(i,n-1)add(read(),read()); 102 size=pow(n,0.666); 103 dfs(1); 104 while(top)belong[sta[top--]]=cnt; 105 for1(i,n)pre[i]=c[i]=read(); 106 int c1=0,c2=0; 107 for1(i,k) 108 { 109 int op=read(); 110 if(op){a[++c1].x=read(),a[c1].y=read(),a[c1].id=c1,a[c1].t=c2;if(belong[a[c1].x]>belong[a[c1].y])swap(a[c1].x,a[c1].y);} 111 else b[++c2].x=read(),b[c2].y=read(),b[c2].id=pre[b[c2].x],pre[b[c2].x]=b[c2].y; 112 } 113 sort(a+1,a+c1+1,cmp); 114 l=r=1,t=0; 115 for1(i,c1) 116 { 117 while(t<a[i].t)t++,color(b[t].x,b[t].y); 118 while(t>a[i].t)color(b[t].x,b[t].id),t--; 119 work(l,a[i].x);work(r,a[i].y); 120 l=a[i].x;r=a[i].y;int f=lca(l,r); 121 change(f); 122 ans[a[i].id]=ret; 123 change(f); 124 } 125 for1(i,c1)printf("%lld\n",ans[i]); 126 return 0; 127 }