BZOJ 2243 树链剖分+ 简单线段树合并

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 10391  Solved: 3987
[Submit][Status][Discuss]

Description

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),

如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

 

Sample Input

6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5

Sample Output

3
1
2

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

Source

第一轮day1

[Submit][Status][Discuss]

回头一想,这个题还是蛮简单的,就是一个pushdown 中的一个小小的错误。。TMD 找了我一晚上!!!!

做法简单来说就是在树链上向上蹦的时候,我们分别考虑x和y 然后判断有没有颜色相邻的情况,有则减1.

代码:

#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1)

using namespace std;
typedef long long ll;
const int N =1e5+5;

struct eee
{
    int v,next;
}edge[N*2];
int tot,head[N];

int dep[N];
int fat[N];
int rak[N];
int idd[N];
int top[N];
int son[N];
int siz[N];
int cnt;

int cc[N];
int n,m;

struct node
{
    int l,r;
    int lcol,rcol;
    int col;
    int cnt;
    int lz;
}tr[N<<2];

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(son,0,sizeof(son));
    memset(siz,0,sizeof(siz));
}

void add(int u,int v)
{
    edge[++tot].v=v; edge[tot].next=head[u]; head[u]=tot;
}

void dfs1(int u,int fa,int deep)
{
    fat[u]=fa;
    dep[u]=deep;
    siz[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].v;
        if(v==fa) continue;
        dfs1(v,u,deep+1);
        siz[u]+=siz[v];
        if(son[u]==0||siz[v]>siz[son[u]]){
            son[u]=v;
        }
    }
}

void dfs2(int u,int t)
{
    top[u]=t;
    idd[u]=++cnt;
    rak[cnt]=u;
    if(!son[u]) return ;
    dfs2(son[u],t);

    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].v;
        if(v!=son[u]&&v!=fat[u]){
            dfs2(v,v);
        }
    }
}

void push_up(int i)
{
    int ll,lr,rl,rr;
    ll=tr[lson].lcol; lr=tr[lson].rcol; rl=tr[rson].lcol; rr=tr[rson].rcol;
    if(lr==rl){
        tr[i].cnt=tr[lson].cnt+tr[rson].cnt-1;
    }
    else tr[i].cnt=tr[lson].cnt+tr[rson].cnt;
    tr[i].lcol=ll;tr[i].rcol=rr;
}

void push_down(int i)
{
    if(tr[i].lz){
        int &lz=tr[i].lz;
        tr[lson].lz=lz;
        tr[lson].col=tr[lson].lcol=tr[lson].rcol=lz;
        tr[lson].cnt=1;
        tr[rson].lz=lz;
        tr[rson].col=tr[rson].lcol=tr[rson].rcol=lz;
        tr[rson].cnt=1;
        lz=0;
    }
}

void build(int i,int l,int r)
{
    tr[i].l=l; tr[i].r=r; tr[i].col=0;
    tr[i].lcol=tr[i].rcol=0;  tr[i].lz=0;
    if(l==r){
        tr[i].col=tr[i].lcol=tr[i].rcol=cc[rak[l]];
        tr[i].cnt=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    push_up(i);
}

void update(int i,int l,int r,int c)
{
    if(tr[i].l==l&&tr[i].r==r){
        tr[i].lz=c;
        tr[i].col=tr[i].lcol=tr[i].rcol=c;
        tr[i].cnt=1;
        return ;
    }
    push_down(i);
    int mid=(tr[i].l+tr[i].r)>>1;
    if(r<=mid) update(lson,l,r,c);
    else if(l>mid) update(rson,l,r,c);
    else{
        update(lson,l,mid,c);
        update(rson,mid+1,r,c);
    }
    push_up(i);
}

int query(int i,int l,int r,int &ll,int &rr)
{
    if(tr[i].l==l&&tr[i].r==r){
        ll=tr[i].lcol; rr=tr[i].rcol;
        //cout<<"colcolcol "<<ll<<" "<<rr<<endl;
        return tr[i].cnt;
    }
    push_down(i);

    int mid=(tr[i].l+tr[i].r)>>1;
    if(r<=mid) return query(lson,l,r,ll,rr);
    else if(l>mid) return query(rson,l,r,ll,rr);
    else{
        int aa,bb,cc,dd;
        int cnt1,cnt2;
        cnt1=query(lson,l,mid,aa,bb);
        cnt2=query(rson,mid+1,r,cc,dd);
        ll=aa; rr=dd;
        if(bb==cc) return cnt1+cnt2-1;
        else return cnt1+cnt2;
    }
}

void updates(int x,int y,int c)
{
    int fx=top[x]; int fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx]>=dep[fy]){
            //cout<<"ll "<<idd[fx]<<" rr "<<idd[x]<<endl;
            update(1,idd[fx],idd[x],c);
            x=fat[fx];
        }
        else{
            //cout<<"ll "<<idd[fx]<<" rr "<<idd[x]<<endl;
            update(1,idd[fy],idd[y],c);
            y=fat[fy];
        }
        fx=top[x];
        fy=top[y];
    }
    //cout<<" ll "<<idd[x]<<" rr "<<idd[y]<<endl;
    if(idd[x]<=idd[y]) update(1,idd[x],idd[y],c);
    else update(1,idd[y],idd[x],c);
}

int getsums(int x,int y)
{
    int ans=0;
    int cnt,precnt;
    int aa,bb,cc,dd;  /// 跳 x
    int aaa,bbb,ccc,ddd;  ///  跳 y
    int fx=top[x],fy=top[y];
    aa=bb=cc=dd=0;
    aaa=bbb=0;

    while(fx!=fy)
    {
        if(dep[fx]>=dep[fy]){
            ans+=query(1,idd[fx],idd[x],cc,dd);
            if(dd==aa) ans--;
            aa=cc; bb=dd;
            x=fat[fx]; fx=top[x];
        }
        else{
            ans+=query(1,idd[fy],idd[y],ccc,ddd);
            if(ddd==aaa) ans--;
            aaa=ccc; bbb=ddd;
            y=fat[fy]; fy=top[y];
        }
    }
    if(idd[x]<=idd[y]){
        ans+=query(1,idd[x],idd[y],cc,dd);
        if(cc==aa) ans--;
        if(dd==aaa) ans--;
    }
    else{
        ans+=query(1,idd[y],idd[x],ccc,ddd);
        if(ccc==aaa) ans--;
        if(ddd==aa) ans--;
    }
    return ans;
}



int main()
{
    int u,v,c;
    char op[5];

    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&cc[i]);
    for(int i=1;i<=n;i++) cc[i]++;
    init();
    for(int i=1;i<n;i++){
        scanf("%d %d",&u,&v);
        add(u,v);
        add(v,u);
    }

    dfs1(1,1,0);
    dfs2(1,1);
    build(1,1,n);

    //cout<<tr[1].cnt<<endl;


    while(m--)
    {
        scanf("%s",op);
        if(op[0]=='Q'){
            scanf("%d %d",&u,&v);
            int ans=getsums(u,v);
            printf("%d\n",ans);
        }
        else{
            scanf("%d %d %d",&u,&v,&c);
            c++;
            updates(u,v,c);
        }
    }

    return 0;
}

/*

6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6

*/

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/81772456
今日推荐