zoukankan      html  css  js  c++  java
  • BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 256 MB

    题目连接

    http://www.lydsy.com/JudgeOnline/problem.php?id=2243

    Description

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

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

    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

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

    Input

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

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

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

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

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

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


     

    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

    2

    HINT

    题意

    题解:

    树链剖分 倍增lca 线段树

    http://hzwer.com/2561.html

    代码:

    //qscqesze
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define maxn 400001
    #define mod 10007
    #define eps 1e-9
    int Num;
    char CH[20];
    //const int inf=0x7fffffff;   //нчоч╢С
    const int inf=0x3f3f3f3f;
    /*
    
    inline void P(int x)
    {
        Num=0;if(!x){putchar('0');puts("");return;}
        while(x>0)CH[++Num]=x%10,x/=10;
        while(Num)putchar(CH[Num--]+48);
        puts("");
    }
    */
    inline ll read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void P(int x)
    {
        Num=0;if(!x){putchar('0');puts("");return;}
        while(x>0)CH[++Num]=x%10,x/=10;
        while(Num)putchar(CH[Num--]+48);
        puts("");
    }
    //**************************************************************************************
    #define N 100001
    int n,m,cnt,sz,head[N],deep[N],son[N],belong[N],pl[N],v[N],ft[N][18];
    bool vis[N];
    struct seg
    {
        int l,r,lc,rc,s,tag;
    }t[maxn*4];
    struct edge
    {
        int to,next;
    }e[2*maxn];
    void insert(int u,int v)
    {
        e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
        e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
    }
    void dfs1(int x)
    {
        vis[x]=son[x]=1;
        for(int i=1;i<=17;i++)
        {
            if(deep[x]<(1<<i))
                break;
            ft[x][i]=ft[ft[x][i-1]][i-1];
        }
        for(int i=head[x];i;i=e[i].next)
        {
            if(vis[e[i].to])
                continue;
            deep[e[i].to]=deep[x]+1;
            ft[e[i].to][0]=x;
            dfs1(e[i].to);
            son[x]+=son[e[i].to];
        }
    }
    void dfs2(int x,int chain)
    {
        pl[x]=++sz;
        belong[x]=chain;
        int k=0;
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&son[k]<son[e[i].to])
                k=e[i].to;
        if(!k)
            return;
        dfs2(k,chain);
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&k!=e[i].to)
                dfs2(e[i].to,e[i].to);
    }
    int lca(int x,int y)
    {
        if(deep[x]<deep[y])
            swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;i<=17;i++)
            if(t&(1<<i))
                x=ft[x][i];
        for(int i=17;i>=0;i--)
            if(ft[x][i]!=ft[y][i])
            {
                x=ft[x][i];
                y=ft[y][i];
            }
        if(x==y)
            return x;
        return ft[x][0];
    }
    void build(int k,int l,int r)
    {
        t[k].l=l,t[k].r=r,t[k].s=1,t[k].tag=-1;
        if(l==r)
            return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    
    void pushup(int k)
    {
        t[k].lc=t[k<<1].lc;t[k].rc=t[k<<1|1].rc;
        if(t[k<<1].rc^t[k<<1|1].lc)t[k].s=t[k<<1].s+t[k<<1|1].s;
        else t[k].s=t[k<<1].s+t[k<<1|1].s-1;
    }
    void pushdown(int k)
    {
        int tmp=t[k].tag;t[k].tag=-1;
        if(tmp==-1||t[k].l==t[k].r)return;
        t[k<<1].s=t[k<<1|1].s=1;
        t[k<<1].tag=t[k<<1|1].tag=tmp;
        t[k<<1].lc=t[k<<1].rc=tmp;
        t[k<<1|1].lc=t[k<<1|1].rc=tmp;
    }
    void change(int k,int x,int y,int c)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&r==y)
        {t[k].lc=t[k].rc=c;t[k].s=1;t[k].tag=c;return;}
        int mid=(l+r)>>1;
        if(mid>=y)change(k<<1,x,y,c);
        else if(mid<x)change(k<<1|1,x,y,c);
        else
        {
            change(k<<1,x,mid,c);
            change(k<<1|1,mid+1,y,c);
        }
        pushup(k);
    }
    int ask(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&r==y)return t[k].s;
        int mid=(l+r)>>1;
        if(mid>=y)return ask(k<<1,x,y);
        else if(mid<x)return ask(k<<1|1,x,y);
        else
        {
            int tmp=1;
            if(t[k<<1].rc^t[k<<1|1].lc)tmp=0;
            return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y)-tmp;
        }
    }
    int getc(int k,int x)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==r)return t[k].lc;
        int mid=(l+r)>>1;
        if(x<=mid)return getc(k<<1,x);
        else return getc(k<<1|1,x);
    }
    int solvesum(int x,int f)
    {
        int sum=0;
        while(belong[x]!=belong[f])
        {
            sum+=ask(1,pl[belong[x]],pl[x]);
            if(getc(1,pl[belong[x]])==getc(1,pl[ft[belong[x]][0]]))sum--;
            x=ft[belong[x]][0];
        }
        sum+=ask(1,pl[f],pl[x]);
        return sum;
    }
    void solvechange(int x,int f,int c)
    {
        while(belong[x]!=belong[f])
        {
            change(1,pl[belong[x]],pl[x],c);
            x=ft[belong[x]][0];
        }
        change(1,pl[f],pl[x],c);
    }
    void solve()
    {
        int a,b,c;
        dfs1(1);
        dfs2(1,1);
        build(1,1,n);
        for(int i=1;i<=n;i++)
            change(1,pl[i],pl[i],v[i]);
        for(int i=1;i<=m;i++)
        {
            char ch[10];
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                scanf("%d%d",&a,&b);
                int t=lca(a,b);
                printf("%d
    ",solvesum(a,t)+solvesum(b,t)-1);
            }
            else
            {
                scanf("%d%d%d",&a,&b,&c);
                int t=lca(a,b);
                solvechange(a,t,c);solvechange(b,t,c);
            }
        }
    }
    void ini()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&v[i]);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            insert(x,y);
        }
    }
    int main()
    {
        ini();
        solve();
        return 0;
    }
  • 相关阅读:
    装饰器
    闭包函数
    名称空间与作用域
    函数参数 函数对象 函数嵌套
    文件内光标的移动 函数基础 定义函数的三种形式 函数的返回值 调用方式
    文件
    字符编码 文件处理
    人月神话之阅读笔记一
    mysql+servlet+jsp实现数据库的增删改查
    文件与流课后作业
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4475023.html
Copyright © 2011-2022 走看看