BZOJ2819 Nim 树链剖分

Posted WDZRMPCBIT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2819 Nim 树链剖分相关的知识,希望对你有一定的参考价值。

题意:给定一个树,维护:1、u到v是否有必胜策略  2、将u的权值修改为w

题解:BFS版的树链剖分

#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;
}
View Code

(这代码现在貌似TLE了啊……懒得改了,貌似将动态内存改为静态就好)

以上是关于BZOJ2819 Nim 树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 树链剖分题目汇总

BZOJ 2243--染色(树链剖分)

BZOJ 2243 染色 | 树链剖分模板题进阶版

BZOJ2157: 旅游 树链剖分 线段树

BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

BZOJ 2157 旅游(树链剖分+线段树)