• [Bzoj2243][SDOI2011]染色(线段树&&树剖||LCT)


    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2243

    线段树+树链剖分,在线段树需要每次用lt和rt两个数组记录当前区间的左右边界的颜色,向上更新时需要判断左区间的右边界是否和右区间的左边界相等。在剖分求LCA的过程中需要在求值之后查询与下一次求值的边界是否相等。

      1 #include<bits/stdc++.h>
      2 #define lson l,mid,i<<1
      3 #define rson mid+1,r,i<<1|1
      4 using namespace std;
      5 typedef long long ll;
      6 const int maxn = 200005;
      7 const int INF = 2e9;
      8 struct node {
      9     int s, e, next;
     10 }edge[maxn * 2];
     11 int n, m;
     12 int son[maxn], top[maxn], tid[maxn], fat[maxn], siz[maxn], dep[maxn], rak[maxn];
     13 int head[maxn], len, dfx;
     14 //siz保存以i为根的子树节点个数,top保存i节点所在链的顶端节点,son保存i节点的重儿子,fat保存i节点的父亲节点
     15 //dep保存i节点的深度(根为1),,tid保存i节点dfs后的新编号,rak保存新编号i对应的节点(rak[i]=j,tid[j]=i)。
     16 void init() {
     17     memset(head, -1, sizeof(head));
     18     len = 0, dfx = 0;
     19 }
     20 void add(int s, int e) {//邻接表存值
     21     edge[len].s = s;
     22     edge[len].e = e;
     23     edge[len].next = head[s];
     24     head[s] = len++;
     25 }
     26 //搜出每个节点的siz,son,fat,dep
     27 void dfs1(int x, int fa, int d) {
     28     siz[x] = 1, son[x] = -1, fat[x] = fa, dep[x] = d;
     29     for (int i = head[x]; i != -1; i = edge[i].next) {
     30         int y = edge[i].e;
     31         if (y == fa)
     32             continue;
     33         dfs1(y, x, d + 1);
     34         siz[x] += siz[y];
     35         if (son[x] == -1 || siz[y] > siz[son[x]])
     36             son[x] = y;
     37     }
     38 }
     39 //搜出每个节点的top,tid,rak
     40 void dfs2(int x, int c) {
     41     top[x] = c;
     42     tid[x] = ++dfx;
     43     rak[dfx] = x;
     44     if (son[x] == -1)
     45         return;
     46     dfs2(son[x], c);
     47     for (int i = head[x]; i != -1; i = edge[i].next) {
     48         int y = edge[i].e;
     49         if (y == fat[x] || y == son[x])
     50             continue;
     51         dfs2(y, y);
     52     }
     53 }
     54 int a[maxn];
     55 int cr[maxn * 2];
     56 int rt[maxn * 2];
     57 int lt[maxn * 2];
     58 int lazy[maxn * 2];
     59 void up(int i) {
     60     lt[i] = lt[i << 1], rt[i] = rt[i << 1 | 1];
     61     cr[i] = cr[i << 1] + cr[i << 1 | 1];
     62     if (lt[i << 1 | 1] == rt[i << 1])
     63         cr[i]--;
     64 }
     65 void down(int i) {
     66     if (lazy[i] != -1) {
     67         lt[i << 1] = lt[i << 1 | 1] = rt[i << 1] = rt[i << 1 | 1] = lazy[i];
     68         cr[i << 1] = cr[i << 1 | 1] = cr[i];
     69         lazy[i << 1] = lazy[i << 1 | 1] = lazy[i];
     70         lazy[i] = -1;
     71     }
     72 }
     73 void build(int l, int r, int i) {
     74     lazy[i] = -1;
     75     if (l == r) {
     76         cr[i] = 1;
     77         rt[i] = a[rak[l]];
     78         lt[i] = a[rak[l]];
     79         return;
     80     }
     81     int mid = (l + r) >> 1;
     82     build(lson);
     83     build(rson);
     84     up(i);
     85 }
     86 void update(int L, int R, int k, int l, int r, int i) {
     87     if (L <= l && r <= R) {
     88         cr[i] = 1;
     89         lazy[i] = k;
     90         lt[i] = rt[i] = k;
     91         return;
     92     }
     93     down(i);
     94     int mid = (l + r) >> 1;
     95     if (L <= mid)
     96         update(L, R, k, lson);
     97     if (R > mid)
     98         update(L, R, k, rson);
     99     up(i);
    100 }
    101 int qquery(int L, int R, int l, int r, int i) {
    102     if (L <= l && r <= R) return cr[i];
    103     down(i);
    104     int mid = (l + r) >> 1;
    105     if (R <= mid) return qquery(L, R, lson);
    106     if (L > mid) return qquery(L, R, rson);
    107     int ans1 = qquery(L, R, lson);
    108     int ans2 = qquery(L, R, rson);
    109     int ans = ans1 + ans2;
    110     if (rt[i << 1] == lt[i << 1 | 1]) ans--;
    111     return ans;
    112 }
    113 
    114 int dquery(int k, int l, int r, int i) {
    115     if (l == r) {
    116         return lt[i];
    117     }
    118     int mid = (l + r) / 2;
    119     down(i);
    120     if (k <= mid)
    121         return dquery(k, lson);
    122     else
    123         return dquery(k, rson);
    124 }
    125 int solve(int x, int y, int w, int flg) {
    126     int ans = 0;
    127     while (top[x] != top[y]) {
    128         if (dep[top[x]] < dep[top[y]])
    129             swap(x, y);
    130         if (!flg)
    131             update(tid[top[x]], tid[x], w, 1, n, 1);
    132         else {
    133             ans += qquery(tid[top[x]], tid[x], 1, n, 1);
    134             if (dquery(tid[top[x]], 1, n, 1) == dquery(tid[fat[top[x]]], 1, n, 1))
    135                 ans--;
    136         }
    137         x = fat[top[x]];
    138     }
    139     if (dep[x] < dep[y])
    140         swap(x, y);
    141     if (!flg)
    142         update(tid[y], tid[x], w, 1, n, 1);
    143     else {
    144         ans += qquery(tid[y], tid[x], 1, n, 1);
    145         return ans;
    146     }
    147 }
    148 int main() {
    149     while (scanf("%d%d", &n, &m) != EOF) {
    150         for (int i = 1; i <= n; i++)
    151             scanf("%d", &a[i]);
    152         init();
    153         int x, y, z;
    154         for (int i = 0; i < n - 1; i++) {
    155             scanf("%d%d", &x, &y);
    156             add(x, y);
    157             add(y, x);
    158         }
    159         dfs1(1, 0, 1);
    160         dfs2(1, 1);
    161         build(1, n, 1);
    162         while (m--) {
    163             char s[10];
    164             scanf("%s", s);
    165             if (s[0] == 'C') {
    166                 scanf("%d%d%d", &x, &y, &z);
    167                 solve(x, y, z, 0);
    168             }
    169             else {
    170                 scanf("%d%d", &x, &y);
    171                 printf("%d
    ", solve(x, y, 0, 1));
    172             }
    173         }
    174     }
    175 }

     LCT的做法好像更简明,只不过down的时候记得交换lv和rv.

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int maxn = 120010;
      5 ll fa[maxn], ch[maxn][2], siz[maxn], val[maxn], sum[maxn], lv[maxn], rv[maxn], lazy2[maxn], lazy[maxn], st[maxn];//父亲节点,左右儿子节点,当前子数节点个数,当前值,lazy标记,辅助数组。
      6 inline bool isroot(int x) {//判断x是否为所在splay的根
      7     return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
      8 }
      9 inline void pushup(int x) {
     10     lv[x] = ch[x][0] ? lv[ch[x][0]] : val[x];
     11     rv[x] = ch[x][1] ? rv[ch[x][1]] : val[x];
     12     if (ch[x][0] && ch[x][1])sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + 1 - (rv[ch[x][0]] == val[x]) - (lv[ch[x][1]] == val[x]);
     13     else if (ch[x][0])sum[x] = sum[ch[x][0]] + (rv[ch[x][0]] != val[x]);
     14     else if (ch[x][1])sum[x] = sum[ch[x][1]] + (lv[ch[x][1]] != val[x]);
     15     else sum[x] = 1;
     16     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
     17 }
     18 inline void pushr(int x) {
     19     swap(ch[x][0], ch[x][1]);
     20     swap(lv[x], rv[x]);
     21     lazy[x] ^= 1;
     22 }
     23 inline void pushC(int x, int c) {
     24     val[x] = lv[x] = rv[x] = c, sum[x] = 1;
     25     lazy2[x] = c;
     26 }
     27 inline void pushdown(int x) {
     28     if (lazy[x]) {
     29         if (ch[x][0])lazy[ch[x][0]] ^= 1;
     30         if (ch[x][1])lazy[ch[x][1]] ^= 1;
     31         swap(ch[x][0], ch[x][1]);
     32         lazy[x] = 0;
     33     }
     34     if (lazy2[x]) {
     35         if (ch[x][0])pushC(ch[x][0], lazy2[x]);
     36         if (ch[x][1])pushC(ch[x][1], lazy2[x]);
     37         lazy2[x] = 0;
     38     }
     39 }
     40 inline void rotate(int x) {
     41     int y = fa[x], z = fa[y];
     42     int k = ch[y][1] == x;
     43     if (!isroot(y))
     44         ch[z][ch[z][1] == y] = x;
     45     fa[x] = z; ch[y][k] = ch[x][k ^ 1]; fa[ch[x][k ^ 1]] = y;
     46     ch[x][k ^ 1] = y; fa[y] = x;
     47     pushup(y);
     48     pushup(x);
     49 }
     50 inline void splay(int x) {
     51     int f = x, len = 0;
     52     st[++len] = f;
     53     while (!isroot(f))st[++len] = f = fa[f];
     54     while (len)pushdown(st[len--]);
     55     while (!isroot(x)) {
     56         int y = fa[x];
     57         int z = fa[y];
     58         if (!isroot(y))
     59             rotate((ch[y][0] == x) ^ (ch[z][0] == y) ? x : y);
     60         rotate(x);
     61     }
     62     pushup(x);
     63 }
     64 inline void access(int x) {//打通根节点到x的实链
     65     for (int y = 0; x; x = fa[y = x])
     66         splay(x), ch[x][1] = y, pushup(x);
     67 }
     68 inline void makeroot(int x) {//将x变为原树的根
     69     access(x); splay(x); pushr(x);
     70 }
     71 int Findroot(int x) {//找根节点
     72     access(x), splay(x);
     73     while (ch[x][0])
     74         pushdown(x), x = ch[x][0];
     75     splay(x);
     76     return x;
     77 }
     78 inline void split(int x, int y) {//将x到y路径变为play
     79     makeroot(x); access(y); splay(y);
     80 }
     81 inline void Link(int x, int y) {//合法连边
     82     makeroot(x); fa[x] = y;
     83 }
     84 inline void cut(int x, int y) {//合法断边
     85     split(x, y); fa[x] = ch[y][0] = 0; pushup(y);
     86 }
     87 int main() {
     88     int n, q;
     89     scanf("%d%d", &n, &q);
     90     for (int i = 1; i <= n; i++)
     91         scanf("%d", &val[i]), lv[i] = rv[i] = val[i], sum[i] = 1;
     92     int x, y, z;
     93     for (int i = 1; i < n; i++) {
     94         scanf("%d%d", &x, &y);
     95         Link(x, y);
     96     }
     97     while (q--) {
     98         char s[3];
     99         scanf("%s", s);
    100         if (s[0] == 'Q') {
    101             scanf("%d%d", &x, &y);
    102             split(x, y);
    103             printf("%d
    ", sum[y]);
    104         }
    105         else {
    106             scanf("%d%d%d", &x, &y, &z);
    107             split(x, y);
    108             pushC(y, z);
    109         }
    110     }
    111 }
  • 相关阅读:
    SpringBoot自动装配源码
    对称加密、非对称加密、数字签名
    k8s部署mysql数据持久化
    docker部署 springboot 多模块项目+vue
    ES入门及安装软件
    prometheus入门介绍及相关组件、原理讲解
    流水线 Sonar 代码扫描
    postgresql数据库 查询表名、备注及字段、长度、是否可控、是否主键等信息
    Helm中Tiller镜像下载失败的解决办法
    程序员孔乙己
  • 原文地址:https://www.cnblogs.com/sainsist/p/11159853.html
Copyright © 2020-2023  润新知