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
  • 相关阅读:
    Java8 lambda表达式10个示例
    我和阿里云RDS的故事
    Spring Mvc 传递参数要controller出现了400,日期参数全局处理,格式化yyyy-MM-dd 和yyyy-MM-dd HH:mm:ss
    剑指Offer_36_两个链表的第一个公共结点
    剑指Offer_35_数组中的逆序对
    剑指Offer_34_找出字符串中第一个只出现一次的字符
    剑指Offer_33_丑数
    剑指Offer_32_把数组排成最小的数
    剑指Offer_31_整数中1出现的次数(从1到n整数中1出现的次数)
    剑指Offer_30_连续子数组的最大和
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11291129.html
Copyright © 2011-2022 走看看