F. Reverse and Swap (线段树, 思维)

题目:传送门

题意

给你一个长度为 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\n", query(1, 1, 1 << n, x, k, n));

        }

    }

}


int main() {

//    int _; scanf("%d", &_);
//    while(_--) solve();

    solve();

    return 0;
}

 

posted on 2020-09-05 20:10  Willems  阅读(189)  评论(0编辑  收藏  举报

导航