SP10707 COT2 - Count on a tree II【樹上莫隊(歐拉序)模板】

題目鏈接,求鏈上顏色數。

Code:

#include<bits/stdc++.h>
#define maxn 40005
#define maxm 100005
#define S 300
using namespace std;
char cb[1<<20],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<20,stdin),cs==ct)?0:*cs++)
void read(int &a){
	char c;while(!isdigit(c=getc()));
	for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
int n,m,dep[maxn],fa[maxn],siz[maxn],son[maxn],top[maxn],A[maxn*2],st[maxn],ed[maxn],tim,bel[maxn*2];
int fir[maxn],nxt[maxn<<1],to[maxn<<1],tot;
void line(int x,int y){nxt[++tot]=fir[x],fir[x]=tot,to[tot]=y;}
void dfs1(int u,int ff){
	dep[u]=dep[fa[u]=ff]+1,siz[u]=1;
	for(int i=fir[u],v;i;i=nxt[i]) if((v=to[i])!=ff)
		dfs1(v,u),siz[u]+=siz[v],siz[v]>siz[son[u]]&&(son[u]=v);
}
void dfs2(int u,int tp){
	top[u]=tp,A[st[u]=++tim]=u;
	if(son[u]) dfs2(son[u],tp);
	for(int i=fir[u],v;i;i=nxt[i]) if(!top[v=to[i]]) dfs2(v,v);
	A[ed[u]=++tim]=u;
}
int LCA(int u,int v){
	for(;top[u]!=top[v];u=fa[top[u]]) if(dep[top[u]]<dep[top[v]]) swap(u,v);
	return dep[u]<dep[v]?u:v;
}
struct node{
	int l,r,lca,id;
	bool operator < (const node &p)const{return bel[l]==bel[p.l]?(bel[l]&1?r>p.r:r<p.r):bel[l]<bel[p.l];}
}q[maxm];
int ans[maxm],cnt[maxn],num,a[maxn],b[maxn];
bool use[maxn];
void mdf(int x){
	if(use[x]) {if(!--cnt[a[x]]) --num;}
	else {if(!cnt[a[x]]++) ++num;}
	use[x]^=1;
}
int main()
{
	int x,y;
	read(n),read(m);
	for(int i=1;i<=n;i++) read(a[i]),b[i]=a[i];
	sort(b+1,b+1+n); int len=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+len,a[i])-b;
	for(int i=1;i<n;i++) read(x),read(y),line(x,y),line(y,x);
	dfs1(1,0),dfs2(1,1);
	for(int i=1;i<=tim;i++) bel[i]=(i-1)/S;
	for(int i=1,z;i<=m;i++){
		read(x),read(y); if(st[x]>st[y]) swap(x,y);
		if((z=LCA(x,y))==x) q[i]=(node){st[x],st[y],0,i};
		else q[i]=(node){ed[x],st[y],z,i};
	}
	sort(q+1,q+1+m);
	x=1,y=0;
	for(int i=1;i<=m;i++){
		while(x>q[i].l) mdf(A[--x]);
		while(y<q[i].r) mdf(A[++y]);
		while(x<q[i].l) mdf(A[x++]);
		while(y>q[i].r) mdf(A[y--]);
		ans[q[i].id]=num+(q[i].lca&&!cnt[a[q[i].lca]]);
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章