题目:传送门
题意
给你一个长度为 2^n 的序列 a,你有 q 次操作,每次操作有四种情况:
对所有操作4输出答案
思路
操作2,相当于分别执行 swap(k), swap(k - 1), swap(k - 2).... swap(1)
所以,只要维护一下,每个 k 的 swap 次数的奇偶性即可
#include <bits/stdc++.h> #define LL long long #define ULL unsigned long long #define UI unsigned int #define mem(i, j) memset(i, j, sizeof(i)) #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define pb push_back #define make make_pair #define INF 0x3f3f3f3f #define inf LLONG_MAX #define PI acos(-1) #define fir first #define sec second #define lb(x) ((x) & (-(x))) #define dbg(x) cout<<#x<<" = "<<x<<endl; using namespace std; const int N = 2e6 + 5; int n, flag[20], a[N], q; LL t[N]; void build(int rt, int l, int r) { if(l == r) { t[rt] = a[l]; return ; } int mid = (l + r) >> 1; build(rt << 1, l, mid); build(rt<< 1 | 1, mid + 1, r); t[rt] = t[rt << 1] + t[rt << 1 | 1]; } void update(int rt, int l, int r, int pos, int x, int du) { if(l == r && pos == l) { t[rt] = x; return ; } int mid = (l + r) >> 1; if(flag[du]) { if(pos <= mid) update(rt << 1 | 1, l, mid, pos, x, du - 1); else update(rt << 1, mid + 1, r, pos, x, du - 1); } else { if(pos <= mid) update(rt << 1, l, mid, pos, x, du - 1); else update(rt << 1 | 1, mid + 1, r, pos, x, du - 1); } t[rt] = t[rt << 1] + t[rt << 1 | 1]; } LL query(int rt, int l, int r, int L, int R, int du) { if(L <= l && r <= R) return t[rt]; LL res = 0LL; if(flag[du]) { int mid = (l + r) >> 1; if(L <= mid) res += query(rt << 1 | 1, l, mid, L, R, du - 1); if(R > mid) res += query(rt << 1, mid + 1, r, L, R, du - 1); } else { int mid = (l + r) >> 1; if(L <= mid) res += query(rt << 1, l, mid, L, R, du - 1); if(R > mid) res += query(rt << 1 | 1, mid + 1, r, L, R, du - 1); } return res; } void solve() { scanf("%d %d", &n, &q); rep(i, 1, (1 << n)) { scanf("%d", &a[i]); // update(1, 1, (1 << n), i, a[i], n); } build(1, 1, 1 << n); while(q--) { int op; scanf("%d", &op); if(op == 1) { int x, k; scanf("%d %d", &x, &k); update(1, 1, 1 << n, x, k, n); } if(op == 2) { int k; scanf("%d", &k); rep(i, 0, k) flag[i] ^= 1; } if(op == 3) { int k; scanf("%d", &k); flag[k + 1] ^= 1; } if(op == 4) { int x, k; scanf("%d %d", &x, &k); printf("%lld ", query(1, 1, 1 << n, x, k, n)); } } } int main() { // int _; scanf("%d", &_); // while(_--) solve(); solve(); return 0; }