列表

详情


NC205175. 树与异或

描述

给一棵树,点有点权。多次询问,每次给出,问"点到点路径上的不同点权种类数”与“点到点路径上点权是的倍数的点个数"的异或和。即设"点到点路径上的不同点权种类数”,点到点路径上点权是的倍数的点个数",求的结果。

输入描述

第一行,表示数据组数。
接下来每组数据第一行一个数,表示树的大小。
第二行个数,表示每个点的权值。接下来行,每行两个数表示一条边
接下来一个数,表示询问总数。接下来行,每行三个数表示一个询问
保证

输出描述

对于每组数据,第一行输出"Case #id:","id"表示数据序号。
接下来行,每行一个数,表示询问的答案。

示例1

输入:

1
5
1 2 1 2 3
2 3
1 5
2 4
1 2
4
4 5 2
1 3 1
5 3 1
5 2 2

输出:

Case #1:
1
1
7
2

说明:

样例解释:对于(4,5,2),3^2=1。对于(1,3,1),2^3=1。对于(5,3,1),3^4=7。对于(5,2,2),3^1=2。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 2104ms, 内存消耗: 25984K, 提交时间: 2020-04-18 18:40:35

#include<bits/stdc++.h>
#define M 100002
using namespace std;
char c;
int Read(){
	while(!isdigit(c=getchar()));
	int res=c^48;
	while(isdigit(c=getchar()))res=(res<<3)+(res<<1)+(c^48);
	return res;
}
int n,f[M],A[M],dep[M],stk[M],Ans[M],dfn[M],R[M],id1[M],id2[M],tp[M],Big[M],sz[M],S,tot,cnt,top;
int mark[M],ans,mem[M];
vector<int>son[M],W[M],U[M];
struct ll{
	int u,v,z,ID;
}Q[M];
bool cmp(ll a,ll b){
	if(id1[a.u]!=id1[b.u])return id1[a.u]<id1[b.u];
	return dfn[a.v]<dfn[b.v];
}
void dfs(int x,int fa){
	int l=top;
	dfn[x]=++tot,dep[x]=dep[fa]+1,f[x]=fa,sz[x]=1,Big[x]=0;
	for(int i=0;i<son[x].size();++i){
		int y=son[x][i];
		if(y==fa)continue;
		dfs(y,x);
		sz[x]+=sz[y];
		if(sz[y]>sz[Big[x]])Big[x]=y;
		if(top-l>=S){
			++cnt;
			while(top>l)id1[stk[top--]]=cnt;
		}
	}
	R[x]=tot;
	stk[++top]=x;
}
void redfs(int x,int t){
	tp[x]=t;
	if(Big[x])redfs(Big[x],t);
	for(int i=0;i<son[x].size();++i){
		int y=son[x][i];
		if(y==f[x]||y==Big[x])continue;
		redfs(y,y);
	}
}
int LCA(int a,int b){
	while(tp[a]!=tp[b]){
		if(dep[tp[a]]<dep[tp[b]])swap(a,b);
		a=f[tp[a]];
	}
	return dep[a]<dep[b]?a:b;
}
void Go(int u,int v){
	while(u!=v){
		if(dep[u]<dep[v])swap(u,v);
		if(mem[u])mem[u]=0,mark[A[u]]--,ans-=(mark[A[u]]==0);
		else mem[u]=1,mark[A[u]]++,ans+=(mark[A[u]]==1);
		u=f[u];
	}
}
int C[M];
void update(int x,int num){
	while(x<=n){
		C[x]+=num;
		x+=x&-x;
	}
}
int query(int x){
	int res=0;
	while(x){
		res+=C[x];
		x-=x&-x;
	}
	return res;
}
int main(){
	int T=Read(),ca=0,mx;
	while(T--){
		tot=cnt=ans=mx=0;
		n=Read(),S=sqrt(n);
		for(int i=1;i<=n;++i)mx=max(mx,A[i]=Read()),U[A[i]].push_back(i);
		for(int i=1,u,v;i<n;++i){
			u=Read(),v=Read();
			son[u].push_back(v),son[v].push_back(u);
		}
		dfs(1,0),redfs(1,1);
		++cnt;
		while(top)id1[stk[top--]]=cnt;
		for(int i=1;i<=n;++i)id2[i]=i/S;
		int q=Read();
		for(int i=1;i<=q;++i)Q[i].u=Read(),Q[i].v=Read(),Q[i].z=Read(),Q[i].ID=i;
		sort(Q+1,Q+q+1,cmp);
		memset(mem,0,sizeof(mem));
		memset(mark,0,sizeof(mark));
		for(int i=1;i<=q;++i){
			Go(Q[i-1].u,Q[i].u),Go(Q[i-1].v,Q[i].v);
			W[Q[i].z].push_back(i);
			Ans[Q[i].ID]=ans;
			if(mark[A[LCA(Q[i].u,Q[i].v)]]==0)Ans[Q[i].ID]++;
		}
		for(int i=1;i<=mx;++i){
			if(!W[i].size())continue;
			for(int j=i;j<=mx;j+=i){
				for(int k=0;k<U[j].size();++k){
					int y=U[j][k];
					update(dfn[y],1);
					update(R[y]+1,-1);
				}
			}
			for(int j=0;j<W[i].size();++j){
				int y=W[i][j];
				int lca=LCA(Q[y].u,Q[y].v);
				Ans[Q[y].ID]^=(query(dfn[Q[y].u])+query(dfn[Q[y].v])-2*query(dfn[lca])+(A[lca]%i==0));
			}
			for(int j=i;j<=mx;j+=i){
				for(int k=0;k<U[j].size();++k){
					int y=U[j][k];
					update(dfn[y],-1);
					update(R[y]+1,1);
				}
			}
		}
		printf("Case #%d:\n",++ca);
		for(int i=1;i<=q;++i)printf("%d\n",Ans[i]);
		for(int i=1;i<=M-2;++i)son[i].clear(),W[i].clear(),U[i].clear();
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 1240ms, 内存消耗: 41428K, 提交时间: 2020-04-18 08:37:13

#include<bits/stdc++.h>
using namespace std;

#define reg register
typedef long long ll;
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)

#define pb push_back

char IO;
template<class T=int> T rd(){
	T s=0;
	int f=0;
	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
	do s=(s<<1)+(s<<3)+(IO^'0');
	while(isdigit(IO=getchar()));
	return f?-s:s;
}

const int N=1e5+10;

int n,m,len,a[N];
vector <int> G[N],Fac[N];
struct Que{ int x,k,id; };
vector <Que> Q[N];
struct Node{ int l,r,lca,id; } A[N];
int ans[N],dep[N],fa[N][20];
int line[N<<1],L[N],R[N],dfn;

void pre_dfs(int u,int f) {
	line[L[u]=++dfn]=u,fa[u][0]=f;
	rep(i,1,17) fa[u][i]=fa[fa[u][i-1]][i-1];
	for(int v:G[u]) if(v!=f) dep[v]=dep[u]+1,pre_dfs(v,u);
	line[R[u]=++dfn]=u;
}
int LCA(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=0,del=dep[x]-dep[y];(1<<i)<=del;++i) if(del&(1<<i)) x=fa[x][i];
	if(x==y) return x;
	drep(i,17,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}

int vis[N],cnt[N],Now;
void Add(int x){ if((cnt[x]++)==0) Now++; }
void Del(int x){ if((--cnt[x])==0) Now--; }
void Upd(int x){ vis[x]?Del(a[x]):Add(a[x]),vis[x]^=1; }

void dfs(int u,int f) {
	for(int t:Fac[a[u]]) cnt[t]++;
	for(Que t:Q[u]) ans[t.id]+=cnt[t.x]*t.k;
	for(int v:G[u]) if(v!=f) dfs(v,u);
	for(int t:Fac[a[u]]) cnt[t]--;
}

int main(){
	rep(i,1,N-1) for(int j=i;j<N;j+=i) Fac[j].pb(i);
	rep(kase,1,rd()) {
		n=rd();
		rep(i,1,n) G[i].clear(),Q[i].clear(),vis[i]=0;
		rep(i,1,n) a[i]=rd();
		rep(i,2,n) {
			int u=rd(),v=rd();
			G[u].pb(v),G[v].pb(u);
		}
		dfn=0,pre_dfs(1,0);
		len=sqrt(n*2);
		rep(i,1,m=rd()) {
			int x=rd(),y=rd(),z=rd(),lca=LCA(x,y);
			if(L[x]>L[y]) swap(x,y);
			if(lca==x) A[i]=(Node){L[x],L[y],0,i};
			else A[i]=(Node){R[x],L[y],lca,i};
			Q[x].pb((Que){z,1,i}),Q[y].pb((Que){z,1,i});
			Q[lca].pb((Que){z,-1,i}),Q[fa[lca][0]].pb((Que){z,-1,i});
		}
		rep(i,1,m) ans[i]=0;
		dfs(1,0);
		sort(A+1,A+m+1,[&](Node x,Node y){ return x.l/len<y.l/len||(x.l/len==y.l/len && x.r<y.r);});
		int l=1,r=0;
		rep(i,1,m) {
			while(l<A[i].l) Upd(line[l++]);
			while(l>A[i].l) Upd(line[--l]);
			while(r>A[i].r) Upd(line[r--]);
			while(r<A[i].r) Upd(line[++r]);
			if(A[i].lca) Upd(A[i].lca);
			ans[A[i].id]^=Now;
			if(A[i].lca) Upd(A[i].lca);
		}
		rep(i,1,n) cnt[a[i]]=0;
		Now=0;
		printf("Case #%d:\n",kase);
		rep(i,1,m) printf("%d\n",ans[i]);
	}
}


上一题