• BZOJ2243: [SDOI2011]染色


    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 9235  Solved: 3469
    [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

    【题解】

    树剖+sgt,维护色块数,左边颜色,右边颜色,注意颜色可以为0

    询问的时候,用t1,t2分别维护左右两条链的sgt节点合并,以及单链情况的时候,看看是u跳还是v跳(比较深度),决定应该与t1合并还是与t2合并

    t1 t2方向相反,交换其中一个的lc,rc,合并t1,t2即为询问答案

    修改略

    还因为build的时候,把tid当rank了。。。全WA。。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <vector>
      8 #include <map>
      9 #include <string> 
     10 #include <cmath> 
     11 #define min(a, b) ((a) < (b) ? (a) : (b))
     12 #define max(a, b) ((a) > (b) ? (a) : (b))
     13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
     14 template<class T>
     15 inline void swap(T &a, T &b)
     16 {
     17     T tmp = a;a = b;b = tmp;
     18 }
     19 inline void read(int &x)
     20 {
     21     x = 0;char ch = getchar(), c = ch;
     22     while(ch < '0' || ch > '9') c = ch, ch = getchar();
     23     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
     24     if(c == '-') x = -x;
     25 }
     26 const int INF = 0x3f3f3f3f;
     27 const int MAXN = 1000000 + 10;
     28 int n,m,start[MAXN],rank[MAXN],tim,size[MAXN],top[MAXN],son[MAXN],deep[MAXN],fa[MAXN],tid[MAXN], head[MAXN], cnt;
     29 struct Edge
     30 {
     31     int u,v,nxt;
     32     Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;}
     33     Edge(){}
     34 }edge[MAXN << 1];
     35 inline void insert(int a, int b)
     36 {
     37     edge[++cnt] = Edge(a,b,head[a]);
     38     head[a] = cnt;
     39 }
     40 struct Node
     41 {
     42     int l,r,sum,lc,rc,lazy;
     43     Node(){l = r = lazy = lc = rc = -1;sum = 0;}
     44 }node[MAXN << 2];
     45 Node merge(Node &a, Node &b)
     46 {
     47     if(a.l == -1) return b;
     48     else if(b.l == -1) return a;
     49     Node re;
     50     re.l = a.l, re.r = b.r, re.sum = a.sum + b.sum;
     51     if(a.rc == b.lc && a.rc != -1) -- re.sum;
     52     re.lc = a.lc, re.rc = b.rc;
     53     return re;
     54 }
     55 void pushup(int o)
     56 {
     57     if(node[o].lazy == -1) return;
     58     node[o << 1].lazy = node[o << 1 | 1].lazy = node[o].lazy;
     59     node[o << 1].sum = node[o << 1 | 1].sum = 1;
     60     node[o << 1].lc = node[o << 1].rc = node[o << 1 | 1].lc = node[o << 1 | 1].rc = node[o].lazy;
     61     node[o].lazy = -1;
     62 }
     63 void build(int o = 1, int l = 1, int r = n)
     64 {
     65     if(l == r)
     66     {
     67         node[o].l = l,node[o].r = r,node[o].sum = 1,node[o].lc = node[o].rc = start[rank[l]];
     68         return;
     69     }
     70     int mid = (l + r) >> 1;
     71     build(o << 1, l, mid);
     72     build(o << 1 | 1, mid + 1, r);
     73     node[o] = merge(node[o << 1], node[o << 1 | 1]);
     74 }
     75 void modify(int ll, int rr, int k, int o = 1)
     76 {
     77     pushup(o);
     78     if(ll <= node[o].l && rr >= node[o].r)
     79     {
     80         node[o].lc = node[o].rc = node[o].lazy = k;
     81         node[o].sum = 1;
     82         return;
     83     }
     84     int mid = (node[o].l + node[o].r) >> 1;
     85     if(mid >= ll) modify(ll, rr, k, o << 1);
     86     if(mid < rr) modify(ll, rr, k, o << 1 | 1);
     87     node[o] = merge(node[o << 1], node[o << 1 | 1]);
     88 }
     89 Node ask(int ll, int rr, int o = 1)
     90 {
     91     pushup(o);
     92     if(ll <= node[o].l && rr >= node[o].r) return node[o];
     93     Node a, b;
     94     int mid = (node[o].l + node[o].r) >> 1;
     95     if(mid >= ll) a = ask(ll, rr, o << 1);
     96     if(mid < rr) b = ask(ll, rr, o << 1 | 1);
     97     return merge(a, b);
     98 }
     99 void dfs1(int x)
    100 {
    101     size[x] = 1;
    102     for(int pos = head[x];pos;pos = edge[pos].nxt)
    103     {
    104         int v = edge[pos].v;
    105         if(v == fa[x]) continue;
    106         deep[v] = deep[x] + 1, fa[v] = x, dfs1(v), size[x] += size[v];
    107         if(son[x] == -1 || size[v] > size[son[x]]) son[x] = v;
    108     }
    109 }
    110 void dfs2(int u, int tp)
    111 {
    112     top[u] = tp, tid[u] = ++ tim, rank[tim] = u;
    113     if(son[u] == -1) return;
    114     dfs2(son[u], tp);
    115     for(int pos = head[u];pos;pos = edge[pos].nxt)
    116     {
    117         int v = edge[pos].v;
    118         if(v != son[u] & v != fa[u]) dfs2(v, v);
    119     }
    120 }
    121 int query(int u, int v)
    122 {
    123     int f1 = top[u], f2 = top[v], tag = 1;
    124     Node t1, t2, tmp;
    125     while(f1 != f2)
    126     {
    127         if(deep[f1] < deep[f2]) swap(f1, f2), swap(u, v), swap(t1, t2);
    128         tmp = ask(tid[f1], tid[u]);
    129         t1 = merge(tmp, t1);
    130         u = fa[f1];f1 = top[u];
    131     }    
    132     if(deep[u] > deep[v]) swap(u, v);
    133     else if(deep[u] < deep[v]) swap(t1, t2);
    134     tmp = ask(tid[u], tid[v]);
    135     t1= merge(tmp, t1);swap(t1.lc, t1.rc);
    136     tmp = merge(t1, t2);
    137     return tmp.sum;
    138 }
    139 void change(int u, int v, int c)
    140 {
    141     int f1 = top[u], f2 = top[v];
    142     while(f1 != f2)
    143     {
    144         if(deep[f1] < deep[f2]) swap(f1, f2), swap(u, v);
    145         modify(tid[f1], tid[u], c);
    146         u = fa[f1], f1 = top[u]; 
    147     }
    148     if(deep[u] > deep[v]) swap(u, v);
    149     modify(tid[u], tid[v], c);
    150 }
    151 int tmp1,tmp2,tmp3;
    152 char c;
    153 int main()
    154 {
    155     read(n), read(m);
    156     for(int i = 1;i <= n;++ i) read(start[i]);
    157     for(int i = 1;i < n;++ i) read(tmp1), read(tmp2), insert(tmp1, tmp2), insert(tmp2, tmp1);
    158     memset(son, -1, sizeof(son)), dfs1(1), dfs2(1,1), build();
    159     for(int i = 1;i <= m;++ i)
    160     {
    161         scanf("%s", &c);
    162         if(c == 'Q') read(tmp1), read(tmp2), printf("%d
    ", query(tmp1, tmp2)); 
    163         else read(tmp1), read(tmp2), read(tmp3), change(tmp1, tmp2, tmp3);
    164     }
    165     return 0;
    166 }
  • 相关阅读:
    js 产生随机数
    基于bootstrap的multiple-select下拉控件使用
    jqgrid 单列排序和组合排序
    jqgrid 配置行号及行号的宽度
    jqgrid 配置分页大小及下拉项
    jqgrid 滚动分页
    jqgrid 宽度自适应
    jqgrid 行选中multiboxonly属性说明
    jqgrid 谈谈给表格设置列头事件、行事件、内容事件
    jqgrid 加入右键菜单按钮管理
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8383422.html
Copyright © 2020-2023  润新知