KTU Programming Camp (Day 3) A. Queries - 线段树

  • 题意
    • 给出 n 个数a1,a2,...,an q 个操作
      • 1 p x将a_p修改为x
      • 2 a b Elf(i,j)  (aijb) Elf(i,j) 表示 ai xor ai+1 xor ,..., xor aj
    • 题解
      • 首先考虑按位处理,求出前缀异或和。用线段树维护区间内1的数量,0的数量也可以通过此求出来。然后考虑两种操作:
        • 修改操作变成了将 [p,n] 的0和1反转
        • 询问操作变成了求 [a,b] 的1的数量乘此区间0的数量乘按位处理前的位权
    • #include <iostream>
      #include <cstdio>
      #include <cstring>
      #include <algorithm>
      #include <string>
      #include <cmath>
      #include <cstdlib>
      #include <vector>
      #include <queue>
      #include <stack>
      #include <set>
      #include <map>
      #include <bitset>
      //#pragma comment(linker, "/STACK:1024000000,1024000000")
      
      using namespace std;
      
      #define ll long long
      #define SZ(x) ((int)(x).size()) 
      #define ALL(v) (v).begin(), (v).end()
      #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
      #define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i) 
      #define REP(i,a,n) for ( int i=a; i<int(n); i++ )
      #define FOR(i,a,n) for ( int i=n-1; i>= int(a);i-- )
      #define lson rt<<1, L, m
      #define rson rt<<1|1, m, R
      typedef pair<int, int> pii;
      typedef pair<int, int> pll;
      #define mp(x, y) make_pair(x, y)
      #define pb(x) push_back(x)
      #define fi first
      #define se second
      #define CLR(a, b) memset(a, b, sizeof(a))
      #define Max(a, b) a = max(a, b)
      #define Min(a, b) a = min(a, b)
      const int maxn = 1e5 + 7;
      const int maxm = 10;
      const int mod = 4001;
      int n, q;
      int a[maxm][maxn];
      ll pw[maxm];
      int pre[maxm][maxn];
      int sum[maxm][maxn << 2];
      int lazy[maxm][maxn << 2];
      void pushUp(int rt, int i){
          int lch = rt << 1, rch = rt << 1 | 1;
          sum[i][rt] = sum[i][lch] + sum[i][rch];
      }
      void pushDown(int rt, int L, int R, int i){
          int lch = rt << 1, rch = rt << 1 | 1;
          int m = (L + R) >> 1;
          if(lazy[i][rt]){
              lazy[i][lch] ^= 1;
              lazy[i][rch] ^= 1;
              sum[i][lch] = m - L - sum[i][lch];
              sum[i][rch] = R - m - sum[i][rch];
              lazy[i][rt] = 0;
          }
      }
      void build(int rt, int L, int R){
          if(L + 1 == R){
              REP(i, 0, maxm) sum[i][rt] = pre[i][L];
              return ;
          }
          int m = (L + R) >> 1;
          build(lson);
          build(rson);
          REP(i, 0, maxm) pushUp(rt, i);
      }
      void update(int rt, int L, int R, int l, int r, int i){
          //printf("%d %d %d\n", L, R, i);
          if(l <= L && r >= R){
              lazy[i][rt] ^= 1;
              sum[i][rt] = R - L - sum[i][rt];
              //printf("%d %d %d\n", L, R, sum[i][rt]);
              return ;
          }
          pushDown(rt, L, R, i);
          int m = (L + R) >> 1;
          if(l < m) update(lson, l, r, i);
          if(r > m) update(rson, l, r, i);
          pushUp(rt, i);
      }
      int query(int rt, int L, int R, int l, int r, int i){
          if(l <= L && r >= R) return sum[i][rt];
          pushDown(rt, L, R, i);
          int m = (L + R) >> 1;
          int v = 0;
          if(l < m) v += query(lson, l, r, i);
          if(r > m) v += query(rson, l, r, i);
          return v;
      }
      int main(){
      #ifdef ac
          freopen("in.txt","r",stdin);
      #endif
          //freopen("out.txt","w",stdout);
          pw[0] = 1;
          REP(i, 1, maxm) pw[i] = pw[i-1] * 2;
          scanf("%d%d", &n, &q);
          REP(i, 1, n + 1){
              int x;
              scanf("%d", &x);
              REP(j, 0, maxm) a[j][i] = x % 2, x /= 2;
              REP(j, 0, maxm) pre[j][i] = pre[j][i-1] ^ a[j][i];
          }
          build(1, 0, n + 1);
          REP(i, 0, q){
              int op, l, r;
              scanf("%d%d%d", &op, &l, &r);
              if(op == 1){
                  REP(i, 0, maxm){
                      int t = r % 2;
                      r /= 2;
                      if(t != a[i][l]) update(1, 0, n + 1, l, n + 1, i);
                      a[i][l] = t;
                  }
              }
              else{
                  l --;
                  r ++;
                  ll res = 0;
                  REP(i, 0, maxm){
                      int v = query(1, 0, n + 1, l, r, i) % mod;
                      res += pw[i] * v % mod * (r - l - v) % mod;
                      res %= mod;
                  }
                  printf("%lld\n", res);
              }
          }
          return 0;
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值