zoukankan      html  css  js  c++  java
  • FZU 2105 Digits Count(位数计算)

    Description

    题目描述

    Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations:

    Operation 1: AND opn L R

    Here opn, L and R are integers.

    For L≤i≤R, we do A[i]=A[i] AND opn (here "AND" is bitwise operation).

    Operation 2: OR opn L R

    Here opn, L and R are integers.

    For L≤i≤R, we do A[i]=A[i] OR opn (here "OR" is bitwise operation).

    Operation 3: XOR opn L R

    Here opn, L and R are integers.

    For L≤i≤R, we do A[i]=A[i] XOR opn (here "XOR" is bitwise operation).

    Operation 4: SUM L R

    We want to know the result of A[L]+A[L+1]+...+A[R].

    Now can you solve this easy problem?

    给定N个整数A={A[0],A[1],...,A[N-1]}。下面有一些操作。

    操作1:AND opn L R

    其中opn,L和R都是整数。

    对于L≤i≤R,我们使A[i]=A[i] AND opn(这里的"AND"是位运算)。

    操作2:OR opn L R

    其中opn,L和R都是整数。

    对于L≤i≤R,我们使A[i]=A[i] OR opn(这里的"OR"是位运算)。

    操作3:XOR opn L R

    其中opn,L和R都是整数。

    对于L≤i≤R,我们使A[i]=A[i] XOR opn(这里的"XOR"是位运算)。

    操作4:SUM L R

    我们想要知道A[L]+A[L+1]+...+A[R]的值。

    现在,你能解决这个简单的问题吗?

    Input

    输入

    The first line of the input contains an integer T, indicating the number of test cases. (T≤100)

    Then T cases, for any case, the first line has two integers n and m (1≤n≤1,000,000, 1≤m≤100,000), indicating the number of elements in A and the number of operations.

    Then one line follows n integers A[0], A[1], ..., A[n-1] (0≤A[i]<16,0≤i<n).

    Then m lines, each line must be one of the 4 operations above. (0≤opn≤15)

    第一行有一个整数T,表示测试样例的数量。(T≤100)

    后面有T个样例,每个样例的第一行有2个整数n和m(1≤n≤1,000,000, 1≤m≤100,000),表示元素数量与操作次数。

    下一行有n个整数A[0], A[1], ..., A[n-1] (0≤A[i]<16,0≤i<n)。

    接着m行,每行都是上述4种操作的其中一个。(0≤opn≤15)

    Output

    输出

    For each test case and for each "SUM" operation, please output the result with a single line.

    对于每个测试样例的每个"SUM"操作,都要输出到单独的一行。

    Sample Input - 输入样例

    Sample Output - 输出样例

    1

    4 4

    1 2 4 7

    SUM 0 2

    XOR 5 0 0

    OR 6 0 3

    SUM 0 2

    7

    18

    【题解】

      单纯的线段树。

      利用线段树查找快速的特点保存元素,对于某段区间内相同状态的元素进行合并。

      进行操作的时候不断查找,直到可操作的区间。因为数据都是非负整数,所以可以用负数标记元素不同的区间。

      PS:状态发生变化的时候都要下压,注意深入的方向。

      PS2:简单的运算速度是高于开辟空间的速度,所以没必要把线段树每个节点的左右区间都记录下来。

      PSP:开辟元素数量4倍的空间一定够用。

    【代码 C++】

     1 #include<cstdio>
     2 int data[1000000 << 4], opn, L, R;
     3 char ts[5];
     4 int build(int data_i, int L, int R){//[L, R]
     5     if (L == R) scanf("%d", &data[data_i]);
     6     else{
     7         int mid = (L + R) >> 1;// [L, mid]  (mid, R]
     8         L = build(data_i << 1 | 1, L, mid);
     9         R = build(data_i + 1 << 1, mid + 1, R);
    10         if (L == R) data[data_i] = L;
    11         else data[data_i] = -1;
    12     }
    13     return data[data_i];
    14 }
    15 int bitwise_peration(int data_i, int L_now, int R_now){
    16     if (data[data_i] != -1 && L <= L_now && R_now <= R){
    17         if (*ts == 'A') data[data_i] &= opn;
    18         else if (*ts == 'O') data[data_i] |= opn;
    19         else if (*ts == 'X') data[data_i] ^= opn;
    20     }
    21     else{
    22         if (data[data_i] != -1) data[data_i << 1 | 1] = data[data_i + 1 << 1] = data[data_i];
    23         int mid = (R_now + L_now) >> 1;
    24         if (R <= mid){// goto Right
    25             L_now = bitwise_peration(data_i << 1 | 1, L_now, mid);
    26             R_now = data[data_i + 1 << 1];
    27         }
    28         else if (mid < L){// goto Left
    29             L_now = data[data_i << 1 | 1];
    30             R_now = bitwise_peration(data_i + 1 << 1, mid + 1, R_now);
    31         }
    32         else{
    33             L_now = bitwise_peration(data_i << 1 | 1, L_now, mid);
    34             R_now = bitwise_peration(data_i + 1 << 1, mid + 1, R_now);
    35         }
    36         if (L_now == R_now) data[data_i] = L_now;
    37         else data[data_i] = -1;
    38     }
    39     return data[data_i];
    40 }
    41 int sum(int data_i, int L_now, int R_now){
    42     if (data[data_i] != -1 && L <= L_now && R_now <= R){
    43         return data[data_i] * (R_now - L_now + 1);
    44     }
    45     if (data[data_i] != -1) data[data_i << 1 | 1] = data[data_i + 1 << 1] = data[data_i];
    46     int mid = (R_now + L_now) >> 1;
    47     if (R <= mid) return sum(data_i << 1 | 1, L_now, mid);
    48     if (mid < L) return sum(data_i + 1 << 1, mid + 1, R_now);
    49     return sum(data_i << 1 | 1, L_now, mid) + sum(data_i + 1 << 1, mid + 1, R_now);
    50 }
    51 int main(){
    52     int t, m, n, i;
    53     for (scanf("%d", &t); t; --t){
    54         scanf("%d%d", &n, &m);
    55         --n;
    56         build(0, 0, n);
    57         while (m--){
    58             scanf("%s", ts);
    59             if (*ts == 'S'){
    60                 scanf("%d%d", &L, &R);
    61                 printf("%d
    ", sum(0, 0, n));
    62             }
    63             else{
    64                 scanf("%d%d%d", &opn, &L, &R);
    65                 bitwise_peration(0, 0, n);
    66             }
    67         }
    68     }
    69     return 0;
    70 }
     1 #include<cstdio>
     2 int L, R;
     3 char data[2097149], opn, ts[5];
     4 int read_g(){// 输入挂
     5     int add = getchar() - '0';
     6     int a = getchar();
     7     while (a >= '0' && a <= '9') add = add * 10 + a - '0', a = getchar();
     8     return add;
     9 }
    10 int build(int data_i, int L, int R){// [L, R]
    11     if (L == R) data[data_i] = read_g();
    12     else{// [L, mid]  (mid, R]
    13         int mid = (L + R) >> 1;
    14         L = build(data_i << 1 | 1, L, mid);
    15         R = build(data_i + 1 << 1, ++mid, R);
    16         if (L == R) data[data_i] = L;
    17         else data[data_i] = -1;
    18     }
    19     return data[data_i];
    20 }
    21 int bitwise_peration(int data_i, int L_now, int R_now){
    22     if (~data[data_i] && L <= L_now && R_now <= R){
    23         if (*ts == 'A') data[data_i] &= opn;
    24         else if (*ts == 'O') data[data_i] |= opn;
    25         else if (*ts == 'X') data[data_i] ^= opn;
    26     }
    27     else{
    28         if (~data[data_i]) data[data_i << 1 | 1] = data[data_i + 1 << 1] = data[data_i];
    29         int mid = (R_now + L_now) >> 1;
    30         if (R <= mid){// goto Right
    31             L_now = bitwise_peration(data_i << 1 | 1, L_now, mid);
    32             R_now = data[data_i + 1 << 1];
    33         }
    34         else if (mid < L){// goto Left
    35             L_now = data[data_i << 1 | 1];
    36             R_now = bitwise_peration(data_i + 1 << 1, mid + 1, R_now);
    37         }
    38         else{
    39             L_now = bitwise_peration(data_i << 1 | 1, L_now, mid);
    40             R_now = bitwise_peration(data_i + 1 << 1, mid + 1, R_now);
    41         }
    42         if (L_now == R_now) data[data_i] = L_now;
    43         else data[data_i] = -1;
    44     }
    45     return data[data_i];
    46 }
    47 int sum(int data_i, int L_now, int R_now){
    48     if (~data[data_i]){
    49         if (L_now < L) L_now = L;
    50         if (R < R_now) R_now = R;
    51         return data[data_i] * (++R_now - L_now);
    52     }
    53     int mid = (R_now + L_now) >> 1;
    54     if (R <= mid) return sum(data_i << 1 | 1, L_now, mid);
    55     if (mid < L) return sum(++data_i << 1, ++mid, R_now);
    56     return sum(data_i << 1 | 1, L_now, mid) + sum(data_i + 1 << 1, mid + 1, R_now);
    57 }
    58 int main(){
    59     int m, n;
    60     short t = read_g();
    61     while (t--){
    62         n = read_g(); m = read_g(); --n;
    63         build(0, 0, n);
    64         while (m--){
    65             scanf("%s", ts); getchar();
    66             if (*ts == 'S'){
    67                 L = read_g(); R = read_g();
    68                 printf("%d
    ", sum(0, 0, n));
    69             }
    70             else{
    71                 opn = read_g(); L = read_g(); R = read_g();
    72                 bitwise_peration(0, 0, n);
    73             }
    74         }
    75     }
    76     return 0;
    77 }

    FZU 2105
     

  • 相关阅读:
    Codeforces1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)总结
    Codeforces 633H Fibonacci-ish II【线段树】
    一些Fibonacci数列的神奇性质【数学】
    Codeforces 620E New Year Tree【线段树傻逼题】
    Codeforces 828C String Reconstruction【并查集巧妙运用】
    Codeforces 559C Gerald and Giant Chess【组合数学】【DP】
    Codeforces 311B Cats Transport【斜率优化DP】
    BZOJ2933 [Poi1999]地图【区间DP】
    BZOJ3688 折线统计【树状数组优化DP】
    BZOJ2131 免费的馅饼【线段树优化DP】
  • 原文地址:https://www.cnblogs.com/Simon-X/p/5202396.html
Copyright © 2011-2022 走看看