zoukankan      html  css  js  c++  java
  • 【中石大2019年我能变强组队训练赛热身赛20190802】E

    Description

    给定一棵树和若干次操作,树上节点的权值一开始都是0,要求完成如下操作:

    令x,y两点间路径上点的点权都乘上一个数

    令x,y两点间路径上点的点权都加上一个数

    令x,y两点间路径上点的点权都按位取反(~)

    查询两点间路径上点的点权之和

    所有答案均对$2^{64}$取模

    Solution

    树链剖分的题目。

    关于对$2^{64}$取模,我们不妨将数组定为unsigned long long类型,这样自然溢出就实现了对这个数的取模。

    关于前两个操作我们维护两个标记即可完成,

    关于对第三个操作,即按位取反操作,我们不妨思考一下按位取反的实现过程,即~x=1111111...1-x,也就是我们将这个操作转换成*(-1)+unsigned long long的最大值即可

    Code

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef unsigned long long ll;
      4 struct node {
      5     int next, to;
      6 } e[200010 << 1];
      7 int num, head[200010];
      8 inline void add(int from, int to) {
      9     e[++num].next = head[from];
     10     e[num].to = to;
     11     head[from] = num;
     12 }
     13 int top[200010], fa[200010], dep[200010], size[200010], son[200010], dfn[200010], cnt;
     14 void dfs1(int now, int f, int d) {
     15     dep[now] = d;
     16     fa[now] = f;
     17     size[now] = 1;
     18     for (register int i = head[now]; i; i = e[i].next) 
     19         if (e[i].to != f) {
     20             dfs1(e[i].to, now, d + 1);
     21             size[now] += size[e[i].to];
     22             if (size[son[now]] < size[e[i].to]) son[now] = e[i].to;
     23         }
     24 }
     25 void dfs2(int now, int f) {
     26     top[now] = f;
     27     dfn[now] = ++cnt;
     28     if (son[now]) dfs2(son[now], f);
     29     for (register int i = head[now]; i; i = e[i].next)
     30         if (e[i].to != son[now] && e[i].to != fa[now]) dfs2(e[i].to, e[i].to);
     31 }
     32 ll sum[200010 << 2];
     33 ll addtag[200010 << 2];
     34 ll addmul[200010 << 2];
     35 int n;
     36 void build(int now, int l, int r) {
     37     sum[now] = addtag[now] = 0;
     38     addmul[now] = 1;
     39     if (l == r) return ;
     40     int mid = l + r >> 1;
     41     build(now << 1, l, mid);
     42     build(now << 1 | 1, mid + 1, r);
     43 }
     44 void pushup(int now) {
     45     sum[now] = sum[now << 1] + sum[now << 1 | 1];
     46 }
     47 void pushdown(int now, ll l, ll r) {
     48     if (addmul[now] != 1) {
     49         sum[now << 1] *= addmul[now];
     50         addmul[now << 1] *= addmul[now];
     51         addtag[now << 1] *= addmul[now];
     52         sum[now << 1 | 1] *= addmul[now];
     53         addmul[now << 1 | 1] *= addmul[now];
     54         addtag[now << 1 | 1] *= addmul[now];      
     55         addmul[now] = 1;
     56     }
     57     if (addtag[now]) {
     58         sum[now << 1] += addtag[now] * l;
     59         addtag[now << 1] += addtag[now];
     60         sum[now << 1 | 1] += addtag[now] * r;
     61         addtag[now << 1 | 1] += addtag[now];      
     62         addtag[now] = 0;
     63     }
     64 }
     65 void updateadd(int now, int l, int r, int x, int y, ll val) {
     66     if (x <= l && r <= y) {
     67         sum[now] += val * (r - l + 1);
     68         addtag[now] += val;
     69         return ;
     70     }
     71     int mid = l + r >> 1;
     72     pushdown(now, mid - l + 1, r - mid);
     73     if (x <= mid) updateadd(now << 1, l, mid, x, y, val);
     74     if (y > mid) updateadd(now << 1 | 1, mid + 1, r, x, y, val);
     75     pushup(now); 
     76 } 
     77 void updatemul(int now, int l, int r, int x, int y, ll val) {
     78     if (x <= l && r <= y) {
     79         sum[now] *= val;
     80         addtag[now] *= val;
     81         addmul[now] *= val;
     82         return ;
     83     }
     84     int mid = l + r >> 1;
     85     pushdown(now, mid - l + 1, r - mid);
     86     if (x <= mid) updatemul(now << 1, l, mid, x, y, val);
     87     if (y > mid) updatemul(now << 1 | 1, mid + 1, r, x, y, val);
     88     pushup(now);    
     89 }
     90 ll query(int now, int l, int r, int x, int y) {
     91     if (x <= l && r <= y) return sum[now];
     92     int mid = l + r >> 1;
     93     pushdown(now, mid - l + 1, r - mid);
     94     ll ret = 0;
     95     if (x <= mid) ret += query(now << 1, l, mid, x, y);
     96     if (y > mid) ret += query(now << 1 | 1, mid + 1, r, x, y);
     97     return ret;
     98 }
     99 void updateadd(int from, int to, ll val) {
    100     while (top[from] != top[to]) {
    101         if (dep[top[from]] < dep[top[to]]) swap(from, to);
    102         updateadd(1, 1, n, dfn[top[from]], dfn[from], val);
    103         from = fa[top[from]];
    104     }
    105     if (dep[from] > dep[to]) swap(from, to);
    106     updateadd(1, 1, n, dfn[from], dfn[to], val);
    107 }
    108 void updatemul(int from, int to, ll val) {
    109     while (top[from] != top[to]) {
    110         if (dep[top[from]] < dep[top[to]]) swap(from, to);
    111         updatemul(1, 1, n, dfn[top[from]], dfn[from], val);
    112         from = fa[top[from]];
    113     }
    114     if (dep[from] > dep[to]) swap(from, to);
    115     updatemul(1, 1, n, dfn[from], dfn[to], val);    
    116 }
    117 ll query(int from, int to) {
    118     ll ret = 0;
    119     while (top[from] != top[to]) {
    120         if (dep[top[from]] < dep[top[to]]) swap(from, to);
    121         ret += query(1, 1, n, dfn[top[from]], dfn[from]);
    122         from = fa[top[from]];
    123     }
    124     if (dep[from] > dep[to]) swap(from, to);
    125     ret += query(1, 1, n, dfn[from], dfn[to]);  
    126     return ret;
    127 }
    128 ll SHLAK = 18446744073709551615;
    129 int main() {
    130     while (~scanf("%d", &n)) {
    131         cnt = 0; num = 0;
    132         memset(head, 0, sizeof(head));
    133         memset(son, 0, sizeof(son));
    134         for (register int i = 2; i <= n; ++i) {
    135             int x; scanf("%d", &x);
    136             add(x, i); add(i, x);
    137         }
    138         dfs1(1, 0, 0);
    139         dfs2(1, 1);
    140         build(1, 1, n);
    141         int m;
    142         scanf("%d", &m);
    143         for (register int i = 1; i <= m; ++i) {
    144             int op, x, y;
    145             ll z;
    146             scanf("%d%d%d", &op, &x, &y);
    147             if (op == 1) {
    148                 scanf("%llu", &z);
    149                 updatemul(x, y, z);
    150             }
    151             else if (op == 2) {
    152                 scanf("%llu", &z);
    153                 updateadd(x, y, z);             
    154             }
    155             else if (op == 3) {
    156                 updatemul(x, y, -1);
    157                 updateadd(x, y, SHLAK);
    158             }
    159             else {
    160                 printf("%llu
    ", query(x, y));
    161             }
    162         }
    163     }
    164     return 0;
    165 }
    AC Code
  • 相关阅读:
    eclipse如何与git 配合工作。
    git托管代码(二)
    PPC2003 安装 CFNET 3.5成功
    我的Window Mobile WCF 項目 第三篇 WM窗体设计
    我的Window Mobile WCF 項目 第一篇Mobile开发和WinForm开发的区别
    我的Window Mobile WCF 項目 第七天
    我的Window Mobile WCF 項目 第二篇 WindowsMobile访问WCF
    WCF 用vs2010 和 vs2008的简单对比测试
    vs2010beta1 和 搜狗输入法 冲突,按下 Ctrl 键就报错,重装搜狗解决
    我的Window Mobile WCF 項目 第六天 (二)
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11291129.html
Copyright © 2011-2022 走看看