BZOJ 2243 染色

Posted on 2016-03-18 22:58  ziliuziliu  阅读(155)  评论(0编辑  收藏  举报

 呀这个还有代码编辑器啊。。我今天才发现。

链剖水题。维护区间左端点和右端点的颜色。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxv 200500
#define maxe 200500
#define maxn 805000
using namespace std;
int n,m,num[maxv],x,y,root=1,nume=0,tot=0,cnt=0,g[maxv];
int dis[maxv],top[maxv],fath[maxv],size[maxv],son[maxv],w[maxv],fw[maxv];
int ls[maxn],rs[maxn],lpos[maxn],rpos[maxn],lazy[maxn],sum[maxn];
int a,b,c;
bool vis[maxv],fff[maxv];
char type[5];
struct edge
{
    int v,nxt;
}e[maxe];
void addedge(int u,int v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs1(int x)
{
    son[x]=0;size[x]=1;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v!=fath[x])
        {
            fath[v]=x;
            dis[v]=dis[x]+1;
            dfs1(v);
            if (size[v]>size[son[x]])
                son[x]=v;
            size[x]=size[x]+size[v];
        }
    }
}
void dfs2(int x,int fa)
{
    w[x]=++cnt;fw[cnt]=x;top[x]=fa;
    if (son[x]!=0) dfs2(son[x],fa);
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if ((v!=fath[x]) && (v!=son[x]))
            dfs2(v,v);
    }
}
void build(int &now,int left,int right)
{
    now=++tot;lpos[now]=0;rpos[now]=0;lazy[now]=-1;
    if (left==right)
    {
        int regis;
        regis=num[fw[left]];
        lpos[now]=regis;rpos[now]=regis;
        sum[now]=1;
        return;
    }
    int mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    lpos[now]=lpos[ls[now]];rpos[now]=rpos[rs[now]];
    sum[now]=sum[ls[now]]+sum[rs[now]];
    if (rpos[ls[now]]==lpos[rs[now]]) sum[now]=sum[now]-1;
}
void pushdown(int now,int left,int right)
{
    if (lazy[now]!=-1)
    {
        lazy[ls[now]]=lazy[now];lazy[rs[now]]=lazy[now];
        lpos[ls[now]]=lazy[now];lpos[rs[now]]=lazy[now];
        rpos[ls[now]]=lazy[now];rpos[rs[now]]=lazy[now];
        sum[ls[now]]=1;sum[rs[now]]=1;
        lazy[now]=-1;
    }
}
void modify(int now,int left,int right,int l,int r,int p)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        lazy[now]=p;sum[now]=1;
        lpos[now]=p;rpos[now]=p;
        return;
    }
    int mid=(left+right)>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r,p);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,p);
    else 
    {
        modify(ls[now],left,mid,l,mid,p);
        modify(rs[now],mid+1,right,mid+1,r,p);
    }
    lpos[now]=lpos[ls[now]];rpos[now]=rpos[rs[now]];
    sum[now]=sum[ls[now]]+sum[rs[now]];
    if (rpos[ls[now]]==lpos[rs[now]]) sum[now]=sum[now]-1;
}
int ask(int now,int left,int right,int l,int r)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
        return sum[now];
    int mid=(left+right)>>1;
    if (r<=mid) return ask(ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r);
    else
    {
        int regis=0;
        regis=ask(ls[now],left,mid,l,mid)+ask(rs[now],mid+1,right,mid+1,r);
        if (rpos[ls[now]]==lpos[rs[now]]) regis--;
        return regis;
    }
}
int find(int now,int left,int right,int p)
{
    pushdown(now,left,right);
    if (left==p) return lpos[now];
    int mid=(left+right)>>1;
    if (p<=mid) return find(ls[now],left,mid,p);
    else return find(rs[now],mid+1,right,p);
}
void work1()
{
    scanf("%d%d%d",&a,&b,&c);
    int f1=top[a],f2=top[b];
    while (f1!=f2)
    {
        if (dis[f1]<dis[f2]) {swap(f1,f2);swap(a,b);}
        modify(root,1,cnt,w[f1],w[a],c);
        a=fath[f1];f1=top[a];
    }
    if (dis[a]>dis[b]) swap(a,b);
    modify(root,1,cnt,w[a],w[b],c);
}
void work2()
{
    int ans=0;
    scanf("%d%d",&a,&b);
    int f1=top[a],f2=top[b];
    while (f1!=f2)
    {
        if (dis[f1]<dis[f2]) {swap(f1,f2);swap(a,b);}
        ans=ans+ask(root,1,cnt,w[f1],w[a]);
        a=fath[f1];
        if (find(root,1,cnt,w[a])==find(root,1,cnt,w[f1]))
            ans--;
        f1=top[a];
    }
    if (dis[a]>dis[b]) swap(a,b);
    ans=ans+ask(root,1,cnt,w[a],w[b]);
    printf("%d\n",ans);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%d",&num[i]);
    for (int i=1;i<=n-1;i++)
    {
        scanf("%d%d",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    dfs1(root);
    dfs2(root,root);
    build(root,1,cnt);
    for (int i=1;i<=m;i++)
    {
        scanf("%s",type);
        if (type[0]=='C') work1();
        else work2();
    }
    return 0;
}