「SCOI2016」幸運數字(在線點分樹+線性基)

題目
恕我直言,這個題用倍增的都是xx
抄WXH代碼的在線點分樹,寫的真是好啊。
但是線性基要用__builtin_clzll優化,快3倍之後纔可以和倍增理論上複雜度優越。
。。。。。。
以後我就這麼寫點分了。

#include<bits/stdc++.h>
#define maxn 20005
#define inf 0x3f3f3f3f
#define LL long long
#define pb push_back
#define FOR(a)\
	for(vector<int>::iterator i=a[u].begin();i!=a[u].end();i++)
using namespace std;

int n,q;
LL f[16][maxn][61],tf[61],G[maxn];
vector<int>e1[maxn],e2[maxn];
int rt,Min,tsz,sz[maxn],d[maxn],fa[maxn],vis[maxn];
void ins(LL *f,LL v){
	for(;v;){
		int i=63-__builtin_clzll(v);
		if(f[i]) v^=f[i];
		else f[i] = v, v=0;
	}
}
void dfs1(int u,int ff,int v=0,int Max=0){
	sz[u]=1;
	FOR(e1) 
		if((v=*i)!=ff && !vis[v])
			dfs1(v,u) , Max = max(Max , sz[v]) , sz[u] += sz[v];
	if(Min>(Max=max(Max,tsz-sz[u]))) Min=Max,rt=u;
}
void dfs2(int u,int ff,LL f[][61],int v=0){
	sz[u] = 1 , ins(f[u],G[u]);
	FOR(e1)
		if(!vis[v=*i] && v!=ff)
			memcpy(f[v],f[u],sizeof (LL)*61),dfs2(v,u,f),sz[u]+=sz[v];
}
int dfs3(int u,int ff,int v=0){
	Min=inf,tsz=sz[u],dfs1(u,0),u=rt,d[u]=d[fa[u]=ff]+1,dfs2(u,0,f[d[u]]),vis[u]=1;
	FOR(e1)
		if(!vis[v=*i])
			e2[u].pb(dfs3(v,u));
	return u;
}
int lca(int u,int v){ for(;u!=v;) d[u]<d[v]?v=fa[v]:u=fa[u];return u; }

int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) scanf("%lld",&G[i]);
	for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),e1[u].pb(v),e1[v].pb(u);
	sz[1]=n,dfs3(1,0);
	for(int i=1,x,y;i<=q;i++){
		scanf("%d%d",&x,&y);int t = lca(x,y);
		memcpy(tf,f[d[t]][x],sizeof tf);
		for(int j=60;~j;j--) ins(tf,f[d[t]][y][j]);
		LL ans = 0;
		for(int j=60;~j;j--) if((ans^tf[j])>ans) ans^=tf[j];
		printf("%lld\n",ans); 
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章