• bzoj 2243 [SDOI2011]染色(树链剖分,线段树)


    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 4637  Solved: 1726
    [Submit][Status][Discuss]

    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

    3

    1

    2

    HINT

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

    Source

    【思路】

           树链剖分,线段树

           线段树维护lc rc c s分别表示线段的左右端颜色 update设置颜色 线段所含颜色数,需要注意的是线段合并以及统计信息时候需要考虑两线段接点是否重色。

           Ps:dep比较的是top,T-T    节点信息加上lr倒是个不错的写法 :)

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<iostream>
      5 #include<algorithm>
      6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      7 using namespace std;
      8 
      9 const int N = 1e5+1e5+10;
     10 
     11 struct Node {
     12     int l,r,lc,rc,c,s;
     13 }T[N<<1];
     14 vector<int> G[N];
     15 int n,m,z,c[N];
     16 char s[2];
     17 
     18 int w[N],top[N],son[N],siz[N],fa[N],dep[N];
     19 
     20 void dfs1(int u) {
     21     siz[u]=1; son[u]=0;
     22     for(int i=0;i<G[u].size();i++) {
     23         int v=G[u][i];
     24         if(v!=fa[u]) {
     25             fa[v]=u; dep[v]=dep[u]+1;
     26             dfs1(v);
     27             if(siz[v]>siz[son[u]]) son[u]=v;
     28             siz[u]+=siz[v];
     29         }
     30     }
     31 }
     32 void dfs2(int u,int tp) {
     33     w[u]=++z; top[u]=tp;
     34     if(son[u]) dfs2(son[u],tp);
     35     for(int i=0;i<G[u].size();i++) {
     36         int v=G[u][i];
     37         if(v!=son[u] && v!=fa[u]) dfs2(v,v);
     38     }
     39 }
     40 void pushdown(int u) {
     41     if(T[u].c!=-1 && T[u].l<T[u].r) {
     42         int lc=u<<1 , rc=lc|1;
     43         T[lc].c=T[rc].c=T[u].c;
     44         T[lc].lc=T[lc].rc=T[rc].lc=T[rc].rc=T[u].c;
     45         T[lc].s=T[rc].s=1;
     46         T[u].c=-1;
     47     }
     48 }
     49 void maintain(int u) {
     50     int lc=u<<1,rc=lc|1;
     51     T[u].lc=T[lc].lc , T[u].rc=T[rc].rc;
     52     T[u].s=T[lc].s+T[rc].s-(T[lc].rc==T[rc].lc);
     53 }
     54 void build(int u,int L,int R) {
     55     T[u].l=L , T[u].r=R , T[u].c=-1 , T[u].s=1;
     56     if(L==R) return ;
     57     int M=(L+R)>>1;
     58     build(u<<1,L,M) , build(u<<1|1,M+1,R);
     59 }
     60 void update(int u,int L,int R,int x) {
     61     pushdown(u);
     62     if(L==T[u].l && R==T[u].r) {                //CC
     63         T[u].c=T[u].lc=T[u].rc=x;
     64         T[u].s=1; return ;
     65     }
     66     int M=(T[u].l+T[u].r)>>1 , lc=u<<1 , rc=lc|1;
     67     if(R<=M) update(lc,L,R,x);                    //can change
     68     else if(L>M) update(rc,L,R,x);
     69     else
     70         update(lc,L,M,x) , update(rc,M+1,R,x);
     71     maintain(u);
     72 }
     73 int query(int u,int L,int R) {
     74     pushdown(u);
     75     if(L==T[u].l && R==T[u].r) return T[u].s;
     76     int M=(T[u].l+T[u].r)>>1 , lc=u<<1 , rc=lc|1;
     77     if(R<=M) return query(lc,L,R);
     78     else if(L>M) return query(rc,L,R);
     79     else
     80         return query(lc,L,M)+query(rc,M+1,R)-(T[lc].rc==T[rc].lc);
     81 }
     82 int find(int u,int r) {
     83     pushdown(u);
     84     if(T[u].l==T[u].r) return T[u].lc;
     85     int M=(T[u].l+T[u].r)>>1;
     86     return r<=M? find(u<<1,r):find(u<<1|1,r);
     87 }
     88 void modify(int u,int v,int x) {
     89     while(top[u]!=top[v]) {
     90         if(dep[top[u]]<dep[top[v]]) swap(u,v);
     91         update(1,w[top[u]],w[u],x);
     92         u=fa[top[u]];
     93     }
     94     if(dep[u]>dep[v]) swap(u,v);
     95     update(1,w[u],w[v],x);
     96 }
     97 int ask(int u,int v) {
     98     int ans=0;
     99     while(top[u]!=top[v]) {
    100         if(dep[top[u]]<dep[top[v]]) swap(u,v);
    101         ans+=query(1,w[top[u]],w[u]);
    102         if(find(1,w[fa[top[u]]])==find(1,w[top[u]])) ans--;
    103         u=fa[top[u]];
    104     }
    105     if(dep[u]>dep[v]) swap(u,v);
    106     ans+=query(1,w[u],w[v]);
    107     return ans;
    108 }
    109 
    110 void read(int& x) {
    111     char c=getchar();
    112     while(!isdigit(c)) c=getchar();
    113     x=0;
    114     while(isdigit(c)) 
    115         x=x*10+c-'0' , c=getchar();
    116 }
    117 int main() {
    118     read(n) , read(m);
    119     FOR(i,1,n) read(c[i]);
    120     int u,v,k;
    121     FOR(i,1,n-1) {
    122         read(u) , read(v);
    123         G[u].push_back(v);
    124         G[v].push_back(u);
    125     }
    126     dfs1(1) , dfs2(1,1);
    127     build(1,1,n);
    128     FOR(i,1,n) update(1,w[i],w[i],c[i]);
    129     while(m--) {
    130         scanf("%s",s);
    131         read(u) , read(v);
    132         if(s[0]=='C')
    133             read(k) , modify(u,v,k);
    134         else
    135             printf("%d
    ",ask(u,v));
    136     }
    137     return 0;
    138 }
  • 相关阅读:
    Educational Codeforces Round 59 (Rated for Div. 2)E. Vasya and Binary String 区间dp
    MySQL语法大全
    D. Buy a Ticket(优先队列+dijkstra)
    Two Sets(并查集分类)
    KMP浅显易懂
    深度理解链式前向星
    快速幂(幂运算取模的logn算法)
    hdu---1950---Bridging signals解题报告(求Lis n*logn贪心+二分搜索)
    dp背包
    线段树模板
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5185642.html
Copyright © 2020-2023  润新知