• 【国家集训队】Tree II


    Description

    给定n个点的树,每个点有点权,维护如下操作:

    • 将某一条链上的点的点权加或者乘一个数
    • 将原有的一条边删除,加入一条新边,并保证操作完之后是一棵树
    • 询问某一条链上所有点权之和

    Solution

    LCT维护

    每一个点维护如下信息:父亲,儿子,点权,子树大小,子树的点权和,翻转标记,乘法标记,加法标记

    这是一道LCT的模板题,难点在于处理三个标记的下放问题

    根据运算优先级,乘法是要先算的,所以先放,放的时候子树的sum,乘法标记,加法标记,儿子的val统统都要乘一遍
    放加法标记的时候,想到线段树的区间大小是稳定的,而Splay并不是,所以还要维护size,于是子树的sum要加上子树的size再乘上标记,而儿子的val和加法标记直接加上该标记的值
    再注意一个小细节即可

    Code

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef unsigned int ll;
      4 const int mod = 51061;
      5 const int N = 1e5 + 10;
      6 inline int read() {
      7     int ret = 0, op = 1;
      8     char c = getchar();
      9     while (!isdigit(c)) {
     10         if (c == '-') op = -1; 
     11         c = getchar();
     12     }
     13     while (isdigit(c)) {
     14         ret = ret * 10 + c - '0';
     15         c = getchar();
     16     }
     17     return ret * op;
     18 }
     19 struct LCT {
     20     int fa, ch[2], size;
     21     ll val;
     22     ll sum;
     23     ll atag, mtag, tag;
     24 } a[N];
     25 int n, m, s[N];
     26 inline void update(int now) {
     27     a[now].size = a[a[now].ch[0]].size + a[a[now].ch[1]].size + 1;
     28     a[now].sum = (a[a[now].ch[0]].sum + a[a[now].ch[1]].sum + a[now].val) % mod;
     29 }
     30 void add(ll &x, int y) {
     31     x += y;
     32     x %= mod;
     33 }    
     34 void mul(ll &x, int y) {
     35     x *= y;
     36     x %= mod;
     37 }
     38 void rev(int now) {
     39     swap(a[now].ch[0], a[now].ch[1]);
     40     a[now].tag ^= 1;
     41 }
     42 void pushdown(int now) {
     43     if (a[now].mtag != 1) {
     44         mul(a[a[now].ch[0]].sum, a[now].mtag); mul(a[a[now].ch[0]].val, a[now].mtag); mul(a[a[now].ch[0]].mtag, a[now].mtag); mul(a[a[now].ch[0]].atag, a[now].mtag);
     45         mul(a[a[now].ch[1]].sum, a[now].mtag); mul(a[a[now].ch[1]].val, a[now].mtag); mul(a[a[now].ch[1]].mtag, a[now].mtag); mul(a[a[now].ch[1]].atag, a[now].mtag);
     46         a[now].mtag = 1;
     47     }
     48     if (a[now].atag) {
     49         add(a[a[now].ch[0]].sum, a[now].atag * a[a[now].ch[0]].size);
     50         add(a[a[now].ch[0]].val, a[now].atag);
     51         add(a[a[now].ch[0]].atag, a[now].atag);
     52         add(a[a[now].ch[1]].sum, a[now].atag * a[a[now].ch[1]].size);
     53         add(a[a[now].ch[1]].val, a[now].atag);
     54         add(a[a[now].ch[1]].atag, a[now].atag);        
     55         a[now].atag = 0;
     56     }
     57     if (a[now].tag) {
     58         if (a[now].ch[0]) rev(a[now].ch[0]);
     59         if (a[now].ch[1]) rev(a[now].ch[1]);
     60         a[now].tag = 0;    
     61     }
     62 }
     63 inline int isnroot(int now) {
     64     return a[a[now].fa].ch[0] == now || a[a[now].fa].ch[1] == now;
     65 }
     66 inline void rotate(int x) {
     67     int y = a[x].fa;
     68     int z = a[y].fa;
     69     int xson = a[y].ch[1] == x;
     70     int yson = a[z].ch[1] == y;
     71     int B = a[x].ch[xson ^ 1];
     72     if (isnroot(y)) a[z].ch[yson] = x; a[x].ch[xson ^ 1] = y; a[y].ch[xson] = B;
     73     if (B) a[B].fa = y; a[y].fa = x; a[x].fa = z;
     74     update(y);
     75 }
     76 inline void splay(int x) {
     77     int y = x, z = 0;
     78     s[++z] = y;
     79     while (isnroot(y)) y = a[y].fa, s[++z] = y;
     80     while (z) pushdown(s[z--]);
     81     while (isnroot(x)) {
     82         y = a[x].fa;
     83         z = a[y].fa;
     84         if (isnroot(y)) 
     85             (a[z].ch[1] == y) ^ (a[y].ch[1] == x) ? rotate(x) : rotate(y);
     86         rotate(x);
     87     }
     88     update(x);
     89 }
     90 void access(int x) {
     91     for (register int y = 0; x; y = x, x = a[x].fa) {
     92         splay(x); a[x].ch[1] = y; update(x);
     93     }
     94 }
     95 void makeroot(int x) {
     96     access(x);
     97     splay(x);
     98     rev(x);
     99 }
    100 void split(int x, int y) {
    101     makeroot(x);
    102     access(y);
    103     splay(y);
    104 }
    105 void link(int x, int y) {
    106     makeroot(x);
    107     a[x].fa = y;
    108 }
    109 void cut(int x, int y) {
    110     split(x, y);
    111     a[x].fa = a[y].ch[0] = 0;
    112 }
    113 int main() {
    114     n = read(); m = read();
    115     for (register int i = 1; i <= n; ++i) {
    116         a[i].val = a[i].size = a[i].mtag = 1;
    117     }
    118     for (register int i = 1; i < n; ++i) {
    119         int x = read(), y = read();
    120         link(x, y);
    121     }
    122     while (m--) {
    123         char op = getchar();
    124         int x0, x1, x2;
    125         if (op == '+') {
    126             x0 = read(), x1 = read(), x2 = read();
    127             split(x0, x1);
    128             add(a[x1].sum, x2 * a[x1].size);
    129             add(a[x1].val, x2);
    130             add(a[x1].atag, x2);
    131         }
    132         else if (op == '-') {
    133             x0 = read(), x1 = read(); cut(x0, x1);
    134             x0 = read(), x1 = read(); link(x0, x1);
    135         }
    136         else if (op == '*') {
    137             x0 = read(), x1 = read(), x2 = read();
    138             split(x0, x1);
    139             mul(a[x1].sum, x2);
    140             mul(a[x1].val, x2);
    141             mul(a[x1].mtag, x2);
    142             mul(a[x1].atag, x2);
    143         }
    144         else {
    145             x0 = read(), x1 = read();
    146             split(x0, x1);
    147             printf("%d
    ", a[x1].sum);
    148         }
    149     }
    150     return 0;
    151 }
    AC Code
  • 相关阅读:
    JavaScript 为字符串添加样式 【每日一段代码80】
    JavaScript replace()方法 【每日一段代码83】
    JavaScript for in 遍历数组 【每日一段代码89】
    JavaScript 创建用于对象的模板【每日一段代码78】
    html5 css3 新元素简单页面布局
    JavaScript Array() 数组 【每日一段代码88】
    JavaScript toUTCString() 方法 【每日一段代码86】
    位运算
    POJ 3259 Wormholes
    POJ 3169 Layout
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11350682.html
Copyright © 2020-2023  润新知