zoukankan      html  css  js  c++  java
  • BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门

    解题思路

      异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度(O(nlog^3n)),并不知道咋过去的。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    const int N=20005;
    
    template<class T> void rd(T &x){
    	x=0; char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    }	
    
    int n,q,head[N],cnt,to[N<<1],nxt[N<<1],f[N][20],dep[N];
    LL w[N];
    
    struct Base{
    	LL a[62];	
    	inline void insert(LL x){
    		if(!x) return ;
    		for(int i=60;~i;i--)
    			if((1ll<<i)&x){
    				if(!a[i]) {a[i]=x; break;}
    				x^=a[i]; if(!x) break;
    			}
    	}
    	inline void clear() {memset(a,0,sizeof(a));}
    	inline LL query(){
    		LL ret=0;
    		for(int i=60;~i;i--)
    			if(a[i] && (ret^a[i])>ret) ret^=a[i];
    		return ret;
    	}
    }b[N][17],ans;
    
    inline void add(int bg,int ed){
    	to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;	
    }
    
    inline void build(Base &zz,Base B){
    	for(int i=60;~i;i--) 
    		if(B.a[i]) zz.insert(B.a[i]);
    }	
    
    void dfs(int x,int F){
    	f[x][0]=F; b[x][0].insert(w[x]);
    	for(int i=1;i<=15;i++) {
    		f[x][i]=f[f[x][i-1]][i-1];
    		if(f[x][i]) b[x][i]=b[x][i-1],build(b[x][i],b[f[x][i-1]][i-1]);
    	}
    	for(int i=head[x];i;i=nxt[i]){
    		int u=to[i]; if(u==F) continue;
    		dep[u]=dep[x]+1; dfs(u,x);	
    	}
    }
    
    inline int LCA(int x,int y){
    	if(dep[x]<dep[y]) swap(x,y);
    	for(int i=15;~i;i--) 
    		if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    	if(x==y) return x;
    	for(int i=15;~i;i--)
    		if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    	return f[x][0];
    }	
    
    inline void solve(int x,int y){
    	int lca=LCA(x,y); ans.clear();
    	for(int i=15;~i;i--)
    		if(dep[f[x][i]]>=dep[lca]) {
     			build(ans,b[x][i]);
    			x=f[x][i];
    		}	
    	for(int i=15;~i;i--)
    		if(dep[f[y][i]]>=dep[lca]){
    			build(ans,b[y][i]);
    			y=f[y][i];	
    		}
    	ans.insert(w[lca]);
    	printf("%lld
    ",ans.query());
    }
    
    int main(){
    	rd(n); rd(q); int x,y;
    	for(int i=1;i<=n;i++) rd(w[i]);
    	for(int i=1;i<n;i++){
    		rd(x); rd(y);
    		add(x,y); add(y,x);	
    	}
    	dep[1]=1; dfs(1,0);
    	while(q--){
    		rd(x),rd(y);
    		solve(x,y);	
    	}
    	return 0;
    }	
    
  • 相关阅读:
    2020以去过半,写一下上半年的总结跟下半年的计划
    js实现浏览器打印功能
    看不见远程新建git分支
    Vue中导出Excel表格方法
    SVN命令使用详解
    IOS NSTimer 定时器用法总结
    静态库与动态库的区别?
    iOS 本地缓存实现 方案借鉴
    IOS开发中NSRunloop跟NSTimer的问题
    FMDB
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10327239.html
Copyright © 2011-2022 走看看