zoukankan      html  css  js  c++  java
  • uva 12501 Bulky process of bulk reduction 线段树(mid)

    UVa Online Judge

      线段树的应用。【成段更新,成段查询】

      因为每个位置都要乘上相应的权值,而且乘的大小依次递增,所以就要构建两棵线段树,一棵记录原始值,另外一个就乘上它所在位置的标号就好了。query的时候就直接两部分相减,得到答案。例如,第一棵树的结点记录为a[i],那么第二棵树的就是i*a[i]了。

      其实这题不难,不过打上来是为了提醒自己注意延迟标记的更新。这题因为延迟标记更新搞错了,所以就产生了严重错误。同时,这次也要感谢Troy师兄,让我明白了debug还是要靠自己的,不是所有问题都有oj帮你检测代码是否通过,不是所有问题的解决都会有标程给你。所以,要证明一个算法没问题,最好还是自己打个暴力的程序,跑一跑随机的数据,然后跟自己优化的算法作比较。

    暴力统计以及随机数据产生的代码:

    View Code
     1 #define prog 1
     2 
     3 #if prog == 0
     4 
     5 #include <cstdio>
     6 #include <cstring>
     7 
     8 const int maxn = 100;
     9 typedef long long ll;
    10 int a[maxn];
    11 
    12 int main() {
    13     int T;
    14 
    15     freopen("in", "r", stdin);
    16     freopen("cmp", "w", stdout);
    17 
    18     scanf("%d", &T);
    19     while (T--) {
    20         int n, m;
    21 
    22         puts("");
    23         scanf("%d%d", &n, &m);
    24         for (int i = 1; i <= n; i++) {
    25             a[i] = 100;
    26         }
    27         while (m--) {
    28             char op[10];
    29 
    30             scanf("%s", op);
    31             if (!strcmp(op, "query")) {
    32                 ll ans = 0;
    33 
    34                 int l, r;
    35 
    36                 scanf("%d%d", &l, &r);
    37                 for (int i = l; i <= r; i++) {
    38                     ans += a[i] * (i - l + 1);
    39                 }
    40                 printf("%lld\n", ans);
    41             } else {
    42                 int l, r, d;
    43 
    44                 scanf("%d%d%d", &l, &r, &d);
    45                 for (int i = l; i <= r; i++) {
    46                     a[i] += d;
    47                 }
    48             }
    49         }
    50     }
    51 
    52     return 0;
    53 }
    54 
    55 #endif
    56 
    57 #if prog == 1
    58 
    59 #include <cstdio>
    60 #include <ctime>
    61 #include <cmath>
    62 #include <algorithm>
    63 #include <cstdlib>
    64 
    65 using namespace std;
    66 
    67 int main() {
    68     int T;
    69 
    70     freopen("in", "w", stdout);
    71     scanf("%d", &T);
    72     printf("%d\n", T);
    73 
    74     srand(time(NULL));
    75     while (T--) {
    76         int n = rand() % 10 + 40, m = rand() % 10 + 40;
    77 
    78         printf("%d %d\n", n, m);
    79         while (m--) {
    80             if (rand() & 1) {
    81                 int a = rand() % n + 1, b = rand() % n + 1;
    82 
    83                 if (a > b) swap(a, b);
    84                 printf("query %d %d\n", a, b);
    85             } else {
    86                 int a = rand() % n + 1, b = rand() % n + 1;
    87 
    88                 if (a > b) swap(a, b);
    89                 printf("change %d %d %d\n", a, b, rand() % 2000 - 1000);
    90             }
    91         }
    92     }
    93 
    94     return 0;
    95 }
    96 
    97 #endif

    AC代码:

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <cstdlib>
      5 
      6 using namespace std;
      7 
      8 #define lson l, m, rt << 1
      9 #define rson m + 1, r, rt << 1 | 1
     10 typedef long long ll;
     11 
     12 const int maxn = 100005;
     13 ll sum1[maxn << 2], sum2[maxn << 2], late[maxn << 2];
     14 
     15 void up(int rt) {
     16     int ls = rt << 1, rs = rt << 1 | 1;
     17 
     18     sum1[rt] = sum1[ls] + sum1[rs];
     19     sum2[rt] = sum2[ls] + sum2[rs];
     20 }
     21 
     22 void down(int rt, int l, int r) {
     23     if (late[rt]) {
     24         int ls = rt << 1, rs = rt << 1 | 1;
     25         int m = (l + r) >> 1;
     26 
     27         late[ls] += late[rt];
     28         late[rs] += late[rt];
     29 
     30         sum1[ls] += late[rt] * (m - l + 1);
     31         sum1[rs] += late[rt] * (r - m);
     32 
     33         sum2[ls] += late[rt] * ((ll)l + m) * (m - l + 1) / 2;
     34         sum2[rs] += late[rt] * ((ll)m + 1 + r) * (r - m) / 2;
     35 
     36         late[rt] = 0;
     37 //        printf("l %d r %d  %lld %lld %lld %lld\n", l, r, sum1[ls], sum1[rs], sum2[ls], sum2[rs]);
     38     }
     39 }
     40 
     41 void build(int l, int r, int rt) {
     42     late[rt] = 0;
     43     if (l == r) {
     44         sum1[rt] = 100;
     45         sum2[rt] = 100 * l;
     46 
     47         return ;
     48     }
     49     int m = (l + r) >> 1;
     50 
     51     build(lson);
     52     build(rson);
     53     up(rt);
     54 }
     55 
     56 void update(int L, int R, ll key, int l, int r, int rt) {
     57     if (L <= l && r <= R) {
     58 //        printf("l %d r %d  %lld\n", l, r, late[rt]);
     59         late[rt] += key;
     60         sum1[rt] += key * (r - l + 1);
     61         sum2[rt] += key * ((ll)l + r) * (r - l + 1) / 2;
     62 
     63         return ;
     64     }
     65     int m = (l + r) >> 1;
     66 
     67     down(rt, l, r);
     68     if (L <= m) update(L, R, key, lson);
     69     if (m < R) update(L, R, key, rson);
     70     up(rt);
     71 //    printf("%d %d : %lld %lld\n", l, r, sum1[rt], sum2[rt]);
     72 }
     73 
     74 ll query(int L, int R, int l, int r, int rt) {
     75     if (L <= l && r <= R) {
     76 //        printf("query %lld %lld\n", sum1[rt], sum2[rt]);
     77         return sum2[rt] - sum1[rt] * (L - 1);
     78     }
     79     int m = (l + r) >> 1;
     80     ll ret = 0;
     81 
     82     down(rt, l, r);
     83     if (L <= m) ret += query(L, R, lson);
     84     if (m < R) ret += query(L, R, rson);
     85 
     86     return ret;
     87 }
     88 
     89 int main() {
     90     int T;
     91     char op[10];
     92 
     93 //    freopen("in", "r", stdin);
     94 //    freopen("out", "w", stdout);
     95 
     96     scanf("%d", &T);
     97 
     98     for (int cc = 1; cc <= T; cc++) {
     99         int n, m;
    100 
    101         scanf("%d%d", &n, &m);
    102         build(1, n, 1);
    103         printf("Case %d:\n", cc);
    104 
    105         while (m--) {
    106             scanf("%s", op);
    107             if (!strcmp(op, "query")) {
    108                 int a, b;
    109 
    110                 scanf("%d%d", &a, &b);
    111                 printf("%lld\n", query(a, b, 1, n, 1));
    112             } else {
    113                 int a, b;
    114                 ll c;
    115 
    116                 scanf("%d%d%lld", &a, &b, &c);
    117                 update(a, b, c, 1, n, 1);
    118             }
    119         }
    120     }
    121 
    122     return 0;
    123 }

      继续学习如何debug!

    ——written by Lyon

  • 相关阅读:
    移动端网页 -- 安卓与IOS兼容
    item上下自动循环滚动显示
    刮刮奖 --- 可以自定义在图层下添加文字等等信息
    内核终端判断,微信?QQ?ipad?IE?移动?Google?opera……
    flexbox布局
    刮刮奖
    constructor
    获取地址栏参数
    this对象
    函数
  • 原文地址:https://www.cnblogs.com/LyonLys/p/uva_12501.html
Copyright © 2011-2022 走看看