zoukankan      html  css  js  c++  java
  • #线性基,点分治#洛谷 3292 [SCOI2016]幸运数字

    题目


    分析

    题目就是将(x)(y)路径上的线性基合并求解,
    这里用的是点分治,每次换根到重心的时候维护前缀线性基,
    查询的时候如果属于不同的子树就能询问答案,记得(x=y)要特判


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #define rr register
    using namespace std;
    typedef long long lll; const int N=20011,M=200011;
    struct node{int y,next;}e[N<<1],E[M<<1]; 
    int n,siz[N],big[N],as[N],SIZ,et=1,Et=1,tot,Q;
    int v[N],root,b[N],is_ed[M],hs[N],st[N]; long long a[N],ans[M];
    inline lll iut(){
    	rr lll ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(lll ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48); 
    }
    struct Vector_Space{
    	lll re[61];
    	inline void BUILD(){
    		memset(re,0,sizeof(re));
    	}
    	inline void Insert(lll x){
    		for (rr int i=60;~i;--i)
    		if ((x>>i)&1){
    			if (!re[i]) {re[i]=x; return;}
    			x^=re[i];
    		}
    	}
    	inline lll query(lll x){
    		for (rr int i=60;~i;--i)
    		    if ((x^re[i])>x) x^=re[i];
    		return x;
    	}
    }H[N];
    inline Vector_Space comb(Vector_Space A,Vector_Space B){
    	rr Vector_Space C; C=A;
    	for (rr int i=60;~i;--i) C.Insert(B.re[i]);
    	return C;
    }
    inline signed max(int a,int b){return a>b?a:b;}
    inline void dfs(int x,int fa){
    	siz[x]=1,big[x]=0;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fa&&!v[e[i].y]){
    		dfs(e[i].y,x);
    		siz[x]+=siz[e[i].y];
    		big[x]=max(big[x],siz[e[i].y]);
    	}
    	big[x]=max(big[x],SIZ-siz[x]);
    	if (big[x]<big[root]) root=x;
    }
    inline void Get(int x,int fa,int bel){
    	st[++tot]=x,b[x]=bel,H[x]=H[fa],H[x].Insert(a[x]);
    	for (rr int i=as[x];i;i=e[i].next)
    	    if (!v[e[i].y]&&e[i].y!=fa) Get(e[i].y,x,bel);
    }
    inline void calc(int x){
    	st[tot=1]=b[x]=x,H[x].BUILD(),H[x].Insert(a[x]);
    	for (rr int i=as[x];i;i=e[i].next)
    	    if (!v[e[i].y]) Get(e[i].y,x,e[i].y);
    	for (rr int i=1;i<=tot;++i)
    	for (rr int j=hs[st[i]];j;j=E[j].next)
    	if (!is_ed[j>>1]&&(b[st[i]]^b[E[j].y]))
    		is_ed[j>>1]=1,ans[j>>1]=comb(H[st[i]],H[E[j].y]).query(0);
    }
    inline void dp(int x){
    	v[x]=1,calc(x);
    	for (rr int i=as[x];i;i=e[i].next)
    	if (!v[e[i].y]){
    		big[0]=SIZ=siz[e[i].y];
    		dfs(e[i].y,root=0),dp(root);
    	}
    }
    signed main(){
    	n=iut(),Q=iut();
    	for (rr int i=1;i<=n;++i) a[i]=iut();
    	for (rr int i=1;i<n;++i){
    		rr int x=iut(),y=iut();
    		e[++et]=(node){y,as[x]},as[x]=et;
    		e[++et]=(node){x,as[y]},as[y]=et;
    	}
    	for (rr int i=1;i<=Q;++i){
    		rr int x=iut(),y=iut();
    		if (x==y) ans[i]=a[x],is_ed[i]=1;
    		E[++Et]=(node){y,hs[x]},hs[x]=Et;
    		E[++Et]=(node){x,hs[y]},hs[y]=Et;
    	}
    	big[0]=SIZ=n,dfs(1,root=0),dp(root);
    	for (rr int i=1;i<=Q;++i)
    	    print(ans[i]),putchar(10);
    	return 0;
    } 
    
  • 相关阅读:
    hdu 1023 卡特兰数+高精度
    hdu 1568 Fibonacci 快速幂
    hdu 3054 Fibonacci 找循环节的公式题
    hdu 5167 Fibonacci 打表
    hdu 4165 Pills dp
    HDU 5791 Two DP
    BZOJ 2152: 聪聪可可 树分治
    HDU 5213 Lucky 莫队+容斥
    HDU 5145 NPY and girls 莫队+逆元
    BZOJ 3289: Mato的文件管理 莫队+BIT
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13930501.html
Copyright © 2011-2022 走看看