- 题意
- 给出
n
个数
a1,a2,...,an 和 q 个操作
1 p x 将a_p修改为x- 2 a b 求 ∑Elf(i,j) (a≤i≤j≤b) , Elf(i,j) 表示 ai xor ai+1 xor ,..., xor aj
- 题解
- 首先考虑按位处理,求出前缀异或和。用线段树维护区间内1的数量,0的数量也可以通过此求出来。然后考虑两种操作:
- 修改操作变成了将 [p,n] 的0和1反转
- 询问操作变成了求 [a,b] 的1的数量乘此区间0的数量乘按位处理前的位权
- 首先考虑按位处理,求出前缀异或和。用线段树维护区间内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; }
- 给出
n
个数
KTU Programming Camp (Day 3) A. Queries - 线段树
最新推荐文章于 2020-02-04 20:16:46 发布