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

    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 6651  Solved: 2432
    [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,表示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]之间。

    Source

    第一轮day1


    裸树链剖分

    太愚蠢了我说怎么全WA最后发现建树时给线段树的节点分配颜色弄错了

    线段树就是普通的颜色覆盖而已,注意两个重链之间判断颜色相同

    加了那个普通的标记剪枝,就bzoj rank16了

    //
    //  main.cpp
    //  sdoi2011染色
    //
    //  Created by Candy on 2016/12/14.
    //  Copyright © 2016年 Candy. All rights reserved.
    //
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define lc o<<1
    #define rc o<<1|1
    #define m ((l+r)>>1)
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    const int N=1e5+5;
    int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,Q,ww[N],w[N],x,y,a,b,c;
    char s[10];
    struct edge{
        int v,ne;
    }e[N<<1];
    int h[N],cnt;
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    int top[N],size[N],tid[N],tot,fa[N],deep[N],mx[N];
    void dfs(int u){
        size[u]++;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v==fa[u]) continue;
            fa[v]=u;deep[v]=deep[u]+1;
            dfs(v);
            size[u]+=size[v];
            if(size[v]>size[mx[u]]) mx[u]=v;
        }
    }
    void dfs(int u,int anc){
        if(!u) return;
        tid[u]=++tot;top[u]=anc;
        dfs(mx[u],anc);
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].v!=fa[u]&&e[i].v!=mx[u]) dfs(e[i].v,e[i].v);
    }
    
    struct node{
        int lv,rv,cnt,tag;
    }t[N<<2];
    inline void merge(int o){
        t[o].tag=-1;
        t[o].lv=t[lc].lv;
        t[o].rv=t[rc].rv;
        t[o].cnt=t[lc].cnt+t[rc].cnt-(t[lc].rv==t[rc].lv);
    }
    inline void paint(int o,int v){
        t[o].tag=t[o].lv=t[o].rv=v;
        t[o].cnt=1;
    }
    void build(int o,int l,int r){
        if(l==r) paint(o,w[l]);
        else{
            build(lson);
            build(rson);
            merge(o);
        }
    }
    inline void pushDown(int o){
        if(t[o].tag!=-1){
            paint(lc,t[o].tag);
            paint(rc,t[o].tag);
            t[o].tag=-1;
        }
    }
    void change(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr) paint(o,v);
        else{
            pushDown(o);
            if(ql<=m) change(lson,ql,qr,v);
            if(m<qr) change(rson,ql,qr,v);
            merge(o);
        }
    }
    int query(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return t[o].cnt;
        else if(t[o].tag!=-1) return 1;
        else{
            pushDown(o);
            int ans=0;
            if(ql<=m) ans+=query(lson,ql,qr);
            if(m<qr) ans+=query(rson,ql,qr);
            if(ql<=m&&m<qr&&t[lc].rv==t[rc].lv) ans--;
            return ans;
        }
    }
    int getcol(int o,int l,int r,int p){
        if(l==r) return t[o].lv;
        else if(t[o].tag!=-1) return t[o].tag;
        else{
            if(p<=m) return getcol(lson,p);
            else return getcol(rson,p);
        }
    }
    void sol1(int x,int y,int c){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            change(1,1,n,tid[top[x]],tid[x],c);
            x=fa[top[x]];
        }
        if(tid[x]>tid[y]) swap(x,y);
        change(1,1,n,tid[x],tid[y],c);
    }
    int sol2(int x,int y){
        int ans=0;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            ans+=query(1,1,n,tid[top[x]],tid[x]);
            if(getcol(1,1,n,tid[top[x]])==getcol(1,1,n,tid[fa[top[x]]])) ans--;
            x=fa[top[x]];
        }
        if(tid[x]>tid[y]) swap(x,y);
        ans+=query(1,1,n,tid[x],tid[y]);
        return ans;
    }
    int main(int argc, const char * argv[]) {
        n=read();Q=read();
        for(int i=1;i<=n;i++) ww[i]=read();
        for(int i=1;i<=n-1;i++) x=read(),y=read(),ins(x,y);
        dfs(1);dfs(1,1);
        for(int i=1;i<=n;i++) w[tid[i]]=ww[i];
        build(1,1,n);
        while(Q--){
            scanf("%s",s);a=read();b=read();
            if(s[0]=='C'){
                c=read();sol1(a,b,c);
            }else printf("%d
    ",sol2(a,b));
        }
        return 0;
    }
  • 相关阅读:
    验证码处理
    表单编码 appliation/x-www-form-urlencoded 与 multipart/form-data 的区别
    python中的 __xxx__ 方法
    scrapy之小试身手
    scrapy之Pipeline
    scrapy之spiders
    exp导出做成批处理注意事项
    oracle V$SESSION各个字段的含义
    【转】ORACLE定期清理INACTIVE会话
    表在用时建索引要加ONLINE
  • 原文地址:https://www.cnblogs.com/candy99/p/6181694.html
Copyright © 2011-2022 走看看