BZOJ2819 Nim 树链剖分+线段树

BFS版的树链剖分

(实际上这代码是TLE的,只需要把动态内存改成静态就可以了,懒得改了就这样吧0.0)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=500000+2;
struct HASH{
    int u;
    HASH *next;
    HASH(){}
    HASH(int _u,HASH *_next):u(_u),next(_next){}
}mem[MAXN*2];
struct NODE{
    int u,v,c,f,son,mark,depth,belong;
    HASH *child;
}node[MAXN],*q[MAXN];
typedef struct TREE{
    int s,l,r;
    TREE *lchild,*rchild;
    TREE(){}
    TREE(int _l,int _r):l(_l),r(_r),lchild(0),rchild(0){}
} *ROOT;
ROOT root;
int N,Q,cnt,mark[MAXN],b,e;
char s[6+2];

void Insert(int u,int v){ node[u].child=&(mem[cnt++]=HASH(v,node[u].child));}

void BFS(int u){
    q[e++]=&node[u],node[u].f=0,node[u].depth=1;
    while(b!=e){
        NODE *t=q[b++];t->c=1;
        for(HASH *p=t->child;p;p=p->next)
            if(p->u!=t->f) q[e++]=&node[p->u],node[p->u].f=t->u,node[p->u].depth=t->depth+1;
    }

    for(int i=e-1;i>=0;i--)
        if(q[i]->f){
            node[q[i]->f].c+=q[i]->c;
            if(q[i]->c>node[node[q[i]->f].son].c) node[q[i]->f].son=q[i]->u;
        }

    for(int i=1;i<=N;i++)
        if(!node[i].mark){
            node[i].mark=++cnt,mark[cnt]=i,node[i].belong=i;
            for(int j=node[i].son;j;j=node[j].son)
                if(!node[j].mark) node[j].mark=++cnt,mark[cnt]=j,node[j].belong=i;
        }
}

void Pushup(ROOT &x){ x->s=x->lchild->s^x->rchild->s;}

void Build(ROOT &x,int l,int r){
    x=new TREE(l,r);
    if(l==r){
        x->s=node[mark[l]].v;
        return;
    }

    int m=(l+r)>>1;
    Build(x->lchild,l,m),Build(x->rchild,m+1,r);

    Pushup(x);
}

int Find(ROOT &x,int l,int r){
    if(x->l>=l && x->r<=r) return x->s;

    int m=(x->l+x->r)>>1,ret=0;
    if(l<=m) ret^=Find(x->lchild,l,r);
    if(r>m) ret^=Find(x->rchild,l,r);

    return ret;
}

int Query(int u,int v){
    int ret=0;

    while(node[u].belong!=node[v].belong){
        if(node[node[u].belong].depth<node[node[v].belong].depth) swap(u,v);
        ret^=Find(root,node[node[u].belong].mark,node[u].mark);
        u=node[node[u].belong].f;
    }

    if(node[u].depth<node[v].depth) swap(u,v);
    ret^=Find(root,node[v].mark,node[u].mark);

    return ret;
}

void Change(ROOT &x,int p,int v){
    if(x->l==x->r){
        x->s=v;
        return;
    }

    int m=(x->l+x->r)>>1;
    if(p<=m) Change(x->lchild,p,v);
    else Change(x->rchild,p,v);

    Pushup(x);
}

int main(){
    memset(node,0,sizeof(node));

    scanf("%d",&N);
    for(int i=1;i<=N;i++) scanf("%d",&node[i].v),node[i].u=i;
    for(int i=1,u,v;i<N;i++){
        scanf("%d %d",&u,&v);
        Insert(u,v),Insert(v,u);
    }

    cnt=0,BFS(1);
    Build(root,1,N);

    scanf("%d",&Q);
    for(int i=1,x,y;i<=Q;i++){
        scanf("%s %d %d",&s,&x,&y);
        if(s[0]=='Q')
            if(Query(x,y)) printf("Yes\n");
            else printf("No\n");
        if(s[0]=='C') Change(root,node[x].mark,y);
    }

    return 0;
}

平衡树+线段树+树链剖分就此告一段落了,实在是写到吐了……一开始的打算是先把链剖给学完然后在SDOI2016R2之前尽量把老师布置的题做一下,LCT是不在考虑的范围之内的,结果……计划没有变化快,就这样了。接下来能不能做到树套树呢,私、気になります!

你可能感兴趣的:(BZOJ2819 Nim 树链剖分+线段树)