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]);
}

  

posted @ 2017-03-24 21:42  SfailSth  阅读(202)  评论(0编辑  收藏  举报