题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3757
题解:
颜色种数不太好用树形数据结构维护,因为子节点的信息不能快速合并为父节点的信息。而莫队算法正是解决这类题目的利器。
节点与节点间的转移可以戳vfleaking的blog:http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
比较巧妙的一点是把麻烦的lca去掉,然后统计答案的时候加上,统计完了再删去。
其实我做这题是为了测试各种树分块的快慢。。。
#1 按王室联邦的分块方法,可以保证所有的块内距离<=sqrt(n),最多有一块的大小>sqrt(n)并且<3sqrt(n)。块内可能是不连通的。
但这对我们算法的执行并没有什么影响,因为它只是作为莫队算法排序的参照(可以说是估价函数)。
块大小sqrt(n) 耗时 8744ms
块大小sqrt(n*log2(n)) 耗时 7520ms
1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm> 10 11 #include<iostream> 12 13 #include<vector> 14 15 #include<map> 16 17 #include<set> 18 19 #include<queue> 20 21 #include<string> 22 23 #define inf 1000000000 24 25 #define maxn 200000+5 26 27 #define maxm 200000+5 28 29 #define eps 1e-10 30 31 #define ll long long 32 33 #define pa pair<int,int> 34 35 #define for0(i,n) for(int i=0;i<=(n);i++) 36 37 #define for1(i,n) for(int i=1;i<=(n);i++) 38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42 43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 44 45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) 46 47 #define mod 1000000007 48 49 using namespace std; 50 51 inline int read() 52 53 { 54 55 int x=0,f=1;char ch=getchar(); 56 57 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 58 59 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 60 61 return x*f; 62 63 } 64 int n,m,size,top,cnt,tot,rt,ti,ret; 65 int a[maxn],head[maxn],ans[maxn],s[maxn],b[maxn],pos[maxn],sta[maxn],f[maxn][18],dep[maxn]; 66 struct rec{int l,r,x,y,id;}q[maxn]; 67 struct edge{int go,next;}e[2*maxn]; 68 bool v[maxn]; 69 inline void add(int x,int y) 70 { 71 e[++tot]=(edge){y,head[x]};head[x]=tot; 72 e[++tot]=(edge){x,head[y]};head[y]=tot; 73 } 74 inline void dfs(int x) 75 { 76 pos[x]=++ti;int tmp=top; 77 for1(i,17)if(dep[x]>=1<<i)f[x][i]=f[f[x][i-1]][i-1];else break; 78 for4(i,x)if(y!=f[x][0]) 79 { 80 f[y][0]=x;dep[y]=dep[x]+1; 81 dfs(y); 82 if(top-tmp>=size) 83 { 84 ++cnt; 85 while(top!=tmp)b[sta[top--]]=cnt; 86 } 87 } 88 sta[++top]=x; 89 } 90 inline int lca(int x,int y) 91 { 92 if(dep[x]<dep[y])swap(x,y); 93 int t=dep[x]-dep[y]; 94 for0(i,17)if(t&(1<<i))x=f[x][i]; 95 if(x==y)return x; 96 for3(i,17,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; 97 return f[x][0]; 98 } 99 inline void change(int x) 100 { 101 if(v[x]){s[a[x]]--;if(!s[a[x]])ret--;} 102 else {s[a[x]]++;if(s[a[x]]==1)ret++;} 103 v[x]^=1; 104 } 105 inline void work(int x,int y) 106 { 107 while(x!=y) 108 { 109 if(dep[x]<dep[y])swap(x,y); 110 change(x); 111 x=f[x][0]; 112 } 113 } 114 inline bool cmp(rec x,rec y){return b[x.l]==b[y.l]?pos[x.r]<pos[y.r]:b[x.l]<b[y.l];} 115 116 int main() 117 118 { 119 120 freopen("input.txt","r",stdin); 121 122 freopen("output.txt","w",stdout); 123 n=read();m=read(); 124 for1(i,n)a[i]=read(); 125 for1(i,n){int x=read(),y=read();add(x,y);if(x*y==0)rt=x+y;} 126 size=sqrt(n); 127 dfs(rt); 128 while(top)b[sta[top--]]=cnt; 129 for1(i,m) 130 { 131 q[i].l=read(),q[i].r=read(),q[i].x=read(),q[i].y=read(),q[i].id=i; 132 if(b[q[i].l]>b[q[i].r])swap(q[i].l,q[i].r); 133 } 134 sort(q+1,q+m+1,cmp); 135 int l=rt,r=rt; 136 for1(i,m) 137 { 138 work(l,q[i].l);work(r,q[i].r); 139 l=q[i].l;r=q[i].r;int f=lca(l,r); 140 change(f); 141 ans[q[i].id]=ret-(int)(q[i].x!=q[i].y&&s[q[i].x]&&s[q[i].y]); 142 change(f); 143 } 144 for1(i,m)printf("%d\n",ans[i]); 145 146 return 0; 147 148 }