• BZOJ2243: [SDOI2011]染色


    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,表示xy之间有一条无向边。

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

    “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]之间。

     
    显然是裸题。。。
    本以为动态树好写一些,然而,然而,一个SB错误瞪了2h+。
    我的代码能力还能用喂狗来形容吗?
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define lc ch[x][0]
    #define rc ch[x][1]
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    int ch[maxn][2],fa[maxn],pre[maxn],setv[maxn],val[maxn];
    int sumv[maxn],left[maxn],right[maxn];
    int s[maxn];
    void maintain(int x) {
        if(!x) return;
        if(setv[x]) {
            left[x]=right[x]=setv[x];sumv[x]=1;
            return;
        }
        sumv[x]=sumv[lc]+sumv[rc]+1;
        if(val[x]==left[rc]) sumv[x]--;
        if(val[x]==right[lc]) sumv[x]--;
        left[x]=left[lc]?left[lc]:val[x];
        right[x]=right[rc]?right[rc]:val[x];
    }
    void set(int x,int v) {
        if(!x) return;
        setv[x]=val[x]=left[x]=right[x]=v;sumv[x]=1;
    }
    void pushdown(int x) {
        if(!x) return;
        if(setv[x]) {
            set(lc,setv[x]);set(rc,setv[x]);
            setv[x]=0;
        }
    }
    void rotate(int x) {
        int y=pre[x],z=pre[y],d=ch[y][0]==x;
        ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y;
        ch[z][ch[z][1]==y]=x;pre[x]=z;
        ch[x][d]=y;pre[y]=x;maintain(y);
    }
    int S[maxn],top;
    void splay(int x) {
        for(int i=x;i;i=pre[i]) S[++top]=i;
        if(top!=1) fa[x]=fa[S[top]],fa[S[top]]=0;
        while(top) pushdown(S[top--]);
        while(pre[x]) rotate(x);
        maintain(x);
    }
    void access(int x) {
        for(int y=0;x;x=fa[x]) {
            splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x;
            ch[x][1]=y;pre[y]=x;maintain(y=x);
        }
    }
    void solve(int x,int y,int t,int v) {
        access(y);
        for(y=0;x;x=fa[x]) {
            splay(x);
            if(!fa[x]) {
                if(t) set(y,v),set(rc,v),val[x]=v,maintain(x);
                else {
                    int ans=sumv[rc]+sumv[y]+1;
                    if(val[x]==left[rc]) ans--;
                    if(val[x]==left[y]) ans--;
                    printf("%d
    ",ans);
                }
                return;
            }
            pre[ch[x][1]]=0;fa[ch[x][1]]=x;
            ch[x][1]=y;pre[y]=x;maintain(y=x);
        }
    }
    int first[maxn],next[maxn<<1],to[maxn<<1],e;
    void AddEdge(int u,int v) {
        to[++e]=v;next[e]=first[u];first[u]=e;
        to[++e]=u;next[e]=first[v];first[v]=e;
    }
    int Q[maxn],vis[maxn];
    void bfs(int x) {
        int l=1,r=0;Q[++r]=x;vis[x]=1;
        while(l<=r) {
            x=Q[l++];
            ren if(!vis[to[i]]) {
                fa[to[i]]=x;
                Q[++r]=to[i];
                vis[to[i]]=1;
            }
        }
    }
    int main() {
        int n=read(),m=read();
        rep(i,1,n) set(i,read()+1);
        rep(i,2,n) AddEdge(read(),read());
        bfs(1);
        while(m--) {
            char c=getchar();while(!isalpha(c)) c=getchar();
            int u=read(),v=read(),x,t=0;
            if(c=='C') x=read()+1,t=1;
            solve(u,v,t,x);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Wordpress 所有hoor列表
    Redis的PHP操作手册(转)
    thinkphp pathinfo nginx 无法加载模块:Index
    gitlab 创建SSH Keys 报500错
    在docker 中配置hadoop1.2.1 cluser
    docker 配置文件引发的问题
    shell在一个大文件找出想要的一段字符串操作技巧
    php关于金额比较引发的问题(转)
    mac 终端乱码
    Swoole笔记(二)
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5027376.html
Copyright © 2020-2023  润新知