bzoj4568: [Scoi2016]幸运数字

树上倍增维护线性基。

一开始以为有什么奥妙,然而并没有。

暴力倍增地维护某点往上2^j个父亲的线性基就好了。合并线性基的时候就暴力把一个往另一个里插。

就是跑得很慢,可能太暴力了。

终于写完scoi2016啦。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=40007;
typedef long long LL;
using namespace std;
int n,q;
LL a[N],d[N],power[61];

template<typename T>void read(T &x)  {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

int ecnt,fir[N],nxt[N],to[N];
void add(int u,int v) {
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
    nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
}

void insert(LL x,LL d[]) {
    for(int i=60;i>=0;i--) if(x&power[i]) {
        if(!d[i]) {d[i]=x; break;}
        else x^=d[i];
    }
}

int f[20003][15],R[N];
LL b[20003][15][61];
void dfs(int x,int fa) {
    f[x][0]=fa; R[x]=R[fa]+1;
    insert(a[x],b[x][0]); insert(a[f[x][0]],b[x][0]);
    for(int i=1;i<15;i++) {
        f[x][i]=f[f[x][i-1]][i-1];
        if(R[x]-power[i]<=0) break;
        for(int j=0;j<=60;j++) b[x][i][j]=b[x][i-1][j];
        for(int j=0;j<=60;j++) 
            insert(b[f[x][i-1]][i-1][j],b[x][i]);
    }
    for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
        dfs(to[i],x);
    }
}

LL qry() {
    LL res=0;
    for(int i=60;i>=0;i--)
        if((res^d[i])>res) res=res^d[i];
    return res;
}

LL get_ans(int x,int y) {
    for(int i=0;i<=60;i++) d[i]=0;
    insert(a[x],d); insert(a[y],d);
    if(R[x]<R[y]) swap(x,y);
    for(int i=14;i>=0;i--) 
        if(R[f[x][i]]>=R[y]) {
            for(int j=0;j<=60;j++)
                insert(b[x][i][j],d);
            x=f[x][i];
        }
    for(int i=14;i>=0;i--) 
        if(f[x][i]!=f[y][i]) {
            for(int j=0;j<=60;j++) {
                insert(b[x][i][j],d);
                insert(b[y][i][j],d);
            }
            x=f[x][i]; y=f[y][i];
        }
    if(x!=y) {
        x=f[x][0];
        insert(a[x],d);
    }
    return qry();
}

int main() {
    read(n); read(q);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<n;i++) {
        int u,v;
        read(u); read(v);
        add(u,v);
    }
    power[0]=1;
    for(int i=1;i<=60;i++) power[i]=power[i-1]*2;
    dfs(1,0);
    while(q--) {
        int x,y;
        read(x); read(y);
        printf("%lld\n",get_ans(x,y));
    }
    return 0;
}
/*
5 1
4 5 4 9 10 
2 1
3 2
4 1
5 3
4 5
*/
View Code

 

posted @ 2018-02-02 20:53  啊宸  阅读(122)  评论(0编辑  收藏  举报