[FWT && 链分治] BZOJ4911.[Sdoi2017]切树游戏

可以看immortalCO大佬的博客

我是参考了Manchery的代码…

#include 
#include 
#include 
#include 

using namespace std;

const int N=30010,M=310,P=10007,inv2=P+1>>1;

inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
    char c=nc(); x=0;
    for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

int n,k,q;

int v[N];
int e[M][M],inv[P+5];

struct U{
    int x,y;
    U(int a=0){
        if(a) x=a,y=0;
        else y=1,x=1;
    }
    friend U operator *(U a,int b){
        if(!b) a.y++; else a.x=a.x*b%P; 
        return a;
    }
    friend U operator /(U a,int b){
        if(!b) a.y--; else a.x=a.x*inv[b]%P;
        return a;
    }
    int val(){
        return y?0:x;
    }
};

U a[N][M];

inline void FWT(int *a,int n,int r){
    for(int i=1;i1)
        for(int j=0;j1)
            for(int k=0;kint x=a[j+k],y=a[j+k+i];
                if(r) a[j+k]=(x+y)%P,a[j+k+i]=(x+P-y)%P;
                else a[j+k]=(x+y)*inv2%P,a[j+k+i]=(x+P-y)*inv2%P;
            } 
}

inline void Pre(int t){
    for(int i=0;i1; FWT(e[i],t,1);
    }
    inv[1]=1;
    for(int i=2;i*inv[P%i]%P; 
} 

int cnt,G[N],fa[N],top[N],dpt[N],size[N],son[N];
struct edge{
    int t,nx;
}E[N<<1];

inline void Insert(int x,int y){
    E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
    E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt;
}

void dfs1(int x,int f){
    fa[x]=f; dpt[x]=dpt[f]+1; size[x]=1;
    for(int i=G[x];i;i=E[i].nx)
        if(E[i].t!=f){
            dfs1(E[i].t,x);
            if(size[E[i].t]>size[son[x]]) son[x]=E[i].t;
            size[x]+=size[E[i].t];
        }
}

vector<int> p[N];

int Q[N];

void dfs2(int x,int t){
    top[x]=t; p[t].push_back(x);
    if(x==t) Q[++*Q]=x;
    if(son[x]) dfs2(son[x],t);
    for(int i=G[x];i;i=E[i].nx)
        if(E[i].t!=fa[x] && son[x]!=E[i].t) dfs2(E[i].t,E[i].t);
}

inline int cmp(const int &a,const int &b){
    return dpt[a]>dpt[b];
}

int icnt,rt[N],ps[N];
int ls[N*3],rs[N*3],ft[N*3],val[N*3][M],lv[N*3][M],rv[N*3][M],pro[N*3][M];

inline void Up(int g){
    for(int i=0;i*lv[rs[g]][i])%P;
        lv[g][i]=(lv[ls[g]][i]+pro[ls[g]][i]*lv[rs[g]][i])%P;
        rv[g][i]=(rv[rs[g]][i]+pro[rs[g]][i]*rv[ls[g]][i])%P;
        pro[g][i]=pro[ls[g]][i]*pro[rs[g]][i]%P;
    }
}

void Build(int &g,int l,int r,int x){
    g=++icnt;
    if(l==r){
        for(int i=0;ix][l-1]][i].val();
        ps[p[x][l-1]]=g;
        return ;
    } 
    int mid=l+r>>1;
    Build(ls[g],l,mid,x); Build(rs[g],mid+1,r,x);
    Up(g); ft[ls[g]]=ft[rs[g]]=g;
}

int ans[M];

inline void Modify(int x){
    int cur=ps[x],y=top[x];
    if(fa[y]){
        for(int i=0;iy]][i]=a[fa[y]][i]/((lv[rt[y]][i]+e[0][i])%P);
    }
    for(int i=0;iy]][i])%P;
    for(int i=0;ix][i].val();
    cur=ft[cur];
    while(cur) Up(cur),cur=ft[cur];
    if(fa[y]){
        for(int i=0;iy]][i]=a[fa[y]][i]*((lv[rt[y]][i]+e[0][i])%P);
    }
    for(int i=0;iy]][i])%P;
}

int tmp[M];

int main(){
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    rea(n); rea(k);
    int t=1; while(t1; k=t;
    Pre(k);
    for(int i=1;i<=n;i++){
        rea(v[i]);
        for(int j=0;jfor(int i=1,x,y;ix),rea(y),Insert(x,y);
    dfs1(1,0); dfs2(1,1);
    sort(Q+1,Q+1+*Q,cmp);
    for(int i=1;i<=*Q;i++){
        int x=Q[i];
        Build(rt[x],1,p[x].size(),x);
        //FWT(val[rt[x]],k,0); for(int j=0;jprintf("%d ",val[rt[x]][j]); putchar('\n'); 
        for(int j=0;jx]][j])%P;
        if(fa[x]){
            for(int j=0;jx]][j]=a[fa[x]][j]*((lv[rt[x]][j]+e[0][j])%P);
        }
    }
    //FWT(ans,k,0); for(int i=0;iprintf("%d ",ans[i]); putchar('\n');
    rea(q);
    while(q--){
        char opt; while((opt=nc())!='Q' && opt!='C');
        if(opt=='C'){
            int x,y; rea(x); rea(y);
            for(int i=0;ix][i]=a[x][i]/e[v[x]][i];
            v[x]=y;
            for(int i=0;ix][i]=a[x][i]*e[v[x]][i];
            while(x)
                Modify(x),x=fa[top[x]];
        }
        else{
            int x; rea(x);
            for(int i=0;i0);
            printf("%d\n",tmp[x]);
        }
    }
    return 0;
}

你可能感兴趣的:(FFT,&,FWT,链分治)