Count on a tree II(树上莫队)

Posted thusloop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Count on a tree II(树上莫队)相关的知识,希望对你有一定的参考价值。

Count on a tree II
题意:树上区间询问 x到y的不同颜色数
欧拉序上查询 ,
不在同一子树上要加上lca的贡献 (ed->st)
在同一子树上(st->st)

//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=8e18;
const int maxn=2e5+100;
int a[maxn],b[maxn],st[maxn],ed[maxn],fa[maxn][30],pos[maxn],use[maxn],dep[maxn];
int cnt[maxn],ans[maxn];
int clk,H,res;
vector<int>g[maxn];
map<int,int>mp;
struct node
{
	int l,r,id,lca;
} t[maxn];
bool cmp(node a,node b)
{
	if(pos[a.l]!=pos[b.l])return pos[a.l]<pos[b.l];
	if(pos[a.l]&1)return a.r<b.r;
	return a.r<b.r;
}
void dfs(int x,int f)
{
	st[x]=++clk;b[clk]=x;
	for(auto it:g[x])
	{
		if(it==f)continue;
		dep[it]=dep[x]+1;
		fa[it][0]=x;
		dfs(it,x);
	}
	ed[x]=++clk;b[clk]=x;
}
int lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int j=H; j>=0; j--)if(dep[fa[x][j]]>=dep[y])x=fa[x][j];	
	if(x==y)return x;
	for(int j=H; j>=0; j--)
	if(fa[x][j]!=fa[y][j]){x=fa[x][j];y=fa[y][j];}
	return fa[x][0];
}
void add(int x)
{
	if(++cnt[x]==1)res++;
}
void del(int x)
{
	if(--cnt[x]==0)res--;
}
void update(int x)
{
	if(use[x]==0) add(a[x]);
	else del(a[x]);
	use[x]^=1;
}
signed main()
{
	int n,q;
	cin>>n>>q;
	H=log2(n);
	int sz=sqrt(n);
	for(int i=1; i<=n; i++){cin>>a[i];mp[a[i]]=1;}
	int mx=0;
	for(auto it:mp)mp[it.fi]=++mx;
	for(int i=1; i<=n; i++)	a[i]=mp[a[i]];
	for(int i=1; i<=2*n; i++)pos[i]=i/sz+1;
	for(int i=1; i<n; i++){int x,y;cin>>x>>y;g[x].pb(y);g[y].pb(x);}
	dep[1]=1;dfs(1,-1);
	for(int j=1; j<=25; j++)
	for(int i=1; i<=n; i++)
	fa[i][j]=fa[fa[i][j-1]][j-1];
	for(int i=1; i<=q; i++)
	{
		int x,y;
		cin>>x>>y;
		if(st[x]>st[y]) swap(x,y);
		int la=lca(x,y);
		if(la==x)t[i]= {st[x],st[y],i,0};
		else t[i]= {ed[x],st[y],i,la};		
	}
	sort(t+1,t+q+1,cmp);
	int l=1,r=0;
	for(int i=1; i<=q; i++)
	{
		while(l>t[i].l) update(b[--l]);
		while(r<t[i].r) update(b[++r]);
		while(l<t[i].l) update(b[l++]);
		while(r>t[i].r) update(b[r--]);
		if(t[i].lca) update(t[i].lca);
		ans[t[i].id]=res;
		if(t[i].lca) update(t[i].lca);
	}
	for(int i=1; i<=q; i++)cout<<ans[i]<<"\\n";
}

以上是关于Count on a tree II(树上莫队)的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ.COT2 Count on a tree II(树上莫队)

SP10707 COT2 - Count on a tree II (树上莫队)

SPOJ10707 COT2 - Count on a tree II 树上莫队

SPOJ COT2 - Count on a tree II(树上莫队)

SPOJ10707COT2 - Count on a tree II

「SPOJ10707」Count on a tree II