记录编号 357341 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [HAOI 2016]地图 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 3.052 s
提交时间 2016-12-10 19:35:38 内存使用 89.19 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N=500010;
//=============边表============
struct edge{int f,t,o;bool vis;}w[N];
int n,m,head[N],tail[N],next[N];
inline void add(int f,int num){
	if (!head[f]) head[f]=tail[f]=num;
		else tail[f]=next[tail[f]]=num;
}
//=============建树============
int fa[N],Fa[N],v[N];
void dfs(int x){//仙人掌化树 
	for (int i=head[x];i;i=next[i])
	if (!w[i].vis){
		w[i].vis=w[w[i].o].vis=1;
		int u=w[i].t;
		if (!fa[u]) fa[u]=Fa[u]=x,dfs(u);
		else for (int v=x;v!=w[i].t;v=Fa[v]) fa[v]=u;
	}
}
int s[N],dfn[N],cnt,q[N],pos[N],size;
vector<int> e[100010];
void dfs1(int x){//求size 
	dfn[x]=++cnt;
	q[++size]=x;
	pos[x]=size;
	s[x]=1;
	for (int i=e[x].size()-1;i>=0;i--){
		q[++size]=x;
		int v=e[x][i];
		dfs1(v);
		s[x]+=s[v];
	}
}
//=============LCA============
int dp[N][20],t[20],lg[N];
void init_st(){//ST求LCA 
	for (int i=1;i<=size;i++) dp[i][0]=q[i];
	t[0]=1;
	for (int i=1;i<19;i++){
		t[i]=1<<i;
		for (int j=t[i-1];j<t[i];j++) lg[j]=i-1;
	}
	for (int j=1;j<19;j++)
	for (int i=1;i<=size-t[j]+1;i++){
		int lc=dp[i][j-1],rc=dp[i+t[j-1]][j-1];
		dp[i][j]=(dfn[lc]<dfn[rc]?lc:rc);
	}
}
int lca(int x,int y){
	x=pos[x];y=pos[y];
	if (x>y) swap(x,y);
	int k=lg[y-x+1],lc=dp[x][k],rc=dp[y-t[k]+1][k];
	return dfn[lc]<dfn[rc]?lc:rc;
}
//=============子树求和============
struct bit{
	int a[N];
	void add(int p,int d){
		if (!p) return;
		for (;p<=n;p+=(p&-p)) a[p]+=d;
	}
	int sum(int r){
		int ans=0;
		for (;r;r-=(r&-r)) ans+=a[r];
		return ans;
	}
	int treesum(int x){
		return sum(dfn[x]+s[x]-1)-sum(dfn[x]-1);
	}
}odd,even;
//=============求解============
struct opt{//k=1表示加点,k=2表示询问,x为操作点,y为参数,id为询问时刻 
	int k,ty,x,y,id;
}Q[N];
bool cmp(const opt &x,const opt &y){
	return x.y==y.y?x.k<y.k:x.y<y.y;
}
struct sit{
	int p,k;
	sit(int P=0){p=P;k=dfn[p];}
	bool operator < (const sit &x)const{return k<x.k;}
};
priority_queue<sit> H;
int X[N],sum[N],color[N],ans[N];//当前各个节点该种拉面出现次数 
void visit(int x,int C){
	if (color[x]==C) return;
	color[x]=C;
	Fa[x]=sum[x]=0;
	H.push(x);
}
void solve(int l,int r){
	static int C=0;C++;
	for (int i=l;i<=r;i++)
		visit(X[i],C),sum[X[i]]++;
	while (!H.empty()){
		int v=H.top().p;H.pop();
		if (!H.empty()){
			int u=H.top().p;
			Fa[v]=lca(u,v);
			visit(Fa[v],C);
			sum[Fa[v]]+=sum[v];
		}
		bit *T=(sum[v]&1?&odd:&even);
		T->add(dfn[v],1);
		T->add(dfn[Fa[v]],-1);
	}
}
int main()
{
	freopen("map_2016.in","r",stdin);
	freopen("map_2016.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d",&v[i]);
	for (int i=1;i<=m;i++){
		scanf("%d%d",&w[i].f,&w[i].t);
		w[i+m]=w[i];
		swap(w[i].f,w[i].t);
		w[i].o=i+m;
		w[i+m].o=i;
		add(w[i].f,i);
		add(w[i].t,i+m);
	}
	Fa[1]=fa[1]=1;dfs(1);
	for (int i=2;i<=n;i++) e[fa[i]].push_back(i);
	dfs1(1);init_st();
	int q;scanf("%d",&q);
	for (int i=1;i<=q;i++){
		scanf("%d%d%d",&Q[i].ty,&Q[i].x,&Q[i].y);
		Q[i].id=i;Q[i].k=2;
	}
	for (int i=1;i<=n;i++)
		Q[q+i].k=1,Q[q+i].x=i,Q[q+i].y=v[i];
	sort(Q+1,Q+q+n+1,cmp);
	for (int i=1;i<=q+n;){
		int flag=Q[i].y,l=i;
		for (;i<=q+n&&Q[i].y==flag&&Q[i].k==1;X[i]=Q[i].x,i++);
		solve(l,i-1);
		for (;i<=q+n&&Q[i].y==flag&&Q[i].k==2;i++)
		if (Q[i].ty==1)
			ans[Q[i].id]=odd.treesum(Q[i].x);
		else
			ans[Q[i].id]=even.treesum(Q[i].x);
	}
	for (int i=1;i<=q;i++) printf("%d\n",ans[i]);
	return 0;
}