zoukankan      html  css  js  c++  java
  • 【国家集训队】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
  • 相关阅读:
    i++与 ++i的 区 别
    css浮动居中实现2
    a MP4Box GUIYamb介绍
    [教程]安装系统解码器 指导教程
    使用AviSynth将高清mov文件导入并重编码为MKV、MP4
    VS2008常用快捷键
    AvsP介绍——非常好用的AviSynth辅助工具
    C/C++语言中Static的作用详述
    [教程]使用Lite MP4 Tool专业制作MP4(AVC)视频格式 指导教程
    Moving Rows in CListCtrl
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11350682.html
Copyright © 2011-2022 走看看