BZOJ2243: [SDOI2011]染色

来源:互联网 发布:东莞网站建设优化技术 编辑:程序博客网 时间:2024/05/22 12:57

题目链接
树链剖分,这题两个区间合并时和Query求值时都需要注意!!!

#include<iostream>#include<cstdio>using namespace std;int n,m,tot,lable,color[410000],Next[410000],head[410000],tree[410000],fa[410000],dep[410000],size[410000];int son[410000],tid[410000],number[410000],top[410000],a[880000],L[880000],R[880000],lazy[880000];bool visit[410000];void add(int x,int y){    tot++;    Next[tot]=head[x];    head[x]=tot;    tree[tot]=y;}void dfs(int x,int depth,int father){    visit[x]=true;fa[x]=father;dep[x]=depth;size[x]=1;son[x]=0;    int maxsize=0;    for (int i=head[x];i;i=Next[i])    if (!visit[tree[i]])    {        dfs(tree[i],depth+1,x);        size[x]+=size[tree[i]];        if (size[tree[i]]>maxsize)        {            maxsize=size[tree[i]];            son[x]=tree[i];        }    }}void dfs1(int x,int ancestor){    visit[x]=true;tid[x]=++lable;number[lable]=x;top[x]=ancestor;    if (son[x]!=0) dfs1(son[x],ancestor);    for (int i=head[x];i;i=Next[i])         if (!visit[tree[i]]) dfs1(tree[i],tree[i]);}void up(int id){    a[id]=a[id*2]+a[id*2+1];    if (R[id*2]==L[id*2+1]) a[id]--;    L[id]=L[id*2];R[id]=R[id*2+1];}void down(int id){    if (lazy[id]!=-1)    {        L[id*2]=R[id*2]=L[id*2+1]=R[id*2+1]=lazy[id];        lazy[id*2]=lazy[id*2+1]=lazy[id];        lazy[id]=-1;        a[id*2]=a[id*2+1]=1;    }}void swap(int &x,int &y){    int t=x;x=y;y=t;}void build(int id,int l,int r){    lazy[id]=-1;L[id]=-1;R[id]=-1;a[id]=0;    if (l==r)     {        a[id]=1;        L[id]=R[id]=color[number[l]];        return;    }    int mid=(l+r)/2;    build(id*2,l,mid);    build(id*2+1,mid+1,r);    up(id);}int query(int x,int y,int id,int l,int r){    if (l>y||r<x) return -1;    down(id);    if (x<=l&&r<=y) return a[id];    int mid=(l+r)/2;    int x1=query(x,y,id*2,l,mid);    int y1=query(x,y,id*2+1,mid+1,r);    if (x1==-1) return y1;    if (y1==-1) return x1;    if (R[id*2]==L[id*2+1]) return x1+y1-1;    return x1+y1;}int find(int id,int l,int r,int x,int y){    down(id);    if (l==r)    {        if (y==0) return L[id];else return R[id];    }    int mid=(l+r)/2;    if (x<=mid) return find(id*2,l,mid,x,y);        else return find(id*2+1,mid+1,r,x,y);}int Query(int x,int y){    int ans=0;    while (top[x]!=top[y])    {        if (dep[top[x]]<dep[top[y]]) swap(x,y);        ans+=query(tid[top[x]],tid[x],1,1,n);        if (find(1,1,n,tid[top[x]],0)==find(1,1,n,tid[fa[top[x]]],1)) ans--;        x=fa[top[x]];    }    if (dep[x]>dep[y]) swap(x,y);    ans+=query(tid[x],tid[y],1,1,n);    return ans;}void change(int x,int y,int id,int l,int r,int d){    if (l>y||r<x) return;    down(id);    if (x<=l&&r<=y)     {        a[id]=1;        L[id]=R[id]=lazy[id]=d;        return;    }    int mid=(l+r)/2;    change(x,y,id*2,l,mid,d);    change(x,y,id*2+1,mid+1,r,d);    up(id);}void Change(int x,int y,int d){    while (top[x]!=top[y])    {        if (dep[top[x]]<dep[top[y]]) swap(x,y);        change(tid[top[x]],tid[x],1,1,n,d);        x=fa[top[x]];    }    if (dep[x]>dep[y]) swap(x,y);    change(tid[x],tid[y],1,1,n,d);}int main(){    scanf("%d%d",&n,&m);    tot=lable=0;    for (int i=1;i<=n;i++) scanf("%d",&color[i]);    for (int i=1;i<n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        add(x,y);add(y,x);    }    for (int i=1;i<=n;i++) visit[i]=false;    dfs(1,1,0);    for (int i=1;i<=n;i++) visit[i]=false;    dfs1(1,1);    build(1,1,n);    char s[100];    for (int i=1;i<=m;i++)    {        scanf("%s",s);        if (s[0]=='Q')        {            int x,y;            scanf("%d%d",&x,&y);            printf("%d\n",Query(x,y));        }else        {            int x,y,z;            scanf("%d%d%d",&x,&y,&z);            Change(x,y,z);        }    }    return 0;}
0 0
原创粉丝点击