BZOJ 3757 苹果树 ——莫队算法
挺好的一道题目,怎么就没有版权了呢?大数据拍过了,精神AC。。。。
发现几种颜色这性质比较垃圾,不可加,莫队硬上。
%了一发popoqqq大神的博客,
看了一波VFK关于糖果公园的博客,
又找了wjmzbmr的博客看了看块状树。
感觉看了很多,明白了:
还TM是抄代码舒服
同序列上的莫队算法,只需要分块,排序之后进行统计,但是要注意更新状态的方法。
根据VFK所说的,为了方便操作,(否则直接暴力维护会有四种情况需要讨论)
我们统计时,把两点间的lca统一去掉,然后类似方法去维护。查询答案时加上、统计、再删去即可。
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 100005 int n,m,col[maxn],h[maxn],to[maxn],ne[maxn],en=0; int f[maxn][20],dep[maxn],sta[maxn],top=0,blo,cnt; int bel[maxn],dfsid[maxn],tot=0,hav[maxn],in[maxn]; int nowans,ans[maxn],siz[maxn]; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } void add(int a,int b) {to[en]=b;ne[en]=h[a];h[a]=en++;} void dfs(int x,int fa) { dfsid[x]=++tot;f[x][0]=fa; if (siz[bel[fa]]==blo) bel[x]=++cnt; else bel[x]=bel[fa]; siz[bel[x]]++; for (int i=h[x];i>=0;i=ne[i]) if (to[i]!=fa){ dep[to[i]]=dep[x]+1; dfs(to[i],x); } } struct Query{ int u,v,a,b,id; void gett(){ u=read();v=read();a=read();b=read(); if (dfsid[u]>dfsid[v]) swap(u,v); } }b[maxn]; bool cmp(Query x,Query y) { return bel[x.u]==bel[y.u]? bel[x.v]<bel[y.v]:bel[x.u]<bel[y.u]; } int lca(int a,int b) { if (dep[a]<dep[b]) swap(a,b); if (a==b) return a; int dist=dep[a]-dep[b]; D(i,15,0) if (dist&(1<<i)) a=f[a][i]; if (a==b) return a; D(i,15,0) if (f[b][i]!=f[a][i]) { b=f[b][i]; a=f[a][i]; } return f[a][0]; } void rev(int x) { if (!x) return; if (in[x]) { in[x]^=1,hav[col[x]]--; if (hav[col[x]]==0) nowans--; } else { in[x]^=1,hav[col[x]]++; if (hav[col[x]]==1) nowans++; } } void rever(int x,int y) { int z=lca(x,y); while (x!=z) rev(x),x=f[x][0]; while (y!=z) rev(y),y=f[y][0]; } int main() { memset(h,-1,sizeof h); n=read();m=read(); blo=sqrt(n+1)+1e-5; F(i,1,n) col[i]=read(); F(i,1,n) { int a,b; a=read();b=read(); add(a,b);add(b,a); } dfs(0,0); while(top)bel[sta[top--]]=cnt; F(i,1,15) F(j,0,n) f[j][i]=f[f[j][i-1]][i-1]; F(i,1,m) b[i].gett(),b[i].id=i; sort(b+1,b+m+1,cmp); int nowu=0,nowv=0; F(i,1,m) { rever(nowu,b[i].u); rever(nowv,b[i].v); nowu=b[i].u;nowv=b[i].v; rev(lca(b[i].u,b[i].v)); ans[b[i].id]=nowans-(hav[b[i].a]&&hav[b[i].b]&&(b[i].a!=b[i].b)); rev(lca(b[i].u,b[i].v)); } F(i,1,m) printf("%d\n",ans[i]); }