zoukankan      html  css  js  c++  java
  • 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
    ", query(1, 1, 1 << n, x, k, n));
    
            }
    
        }
    
    }
    
    
    int main() {
    
    //    int _; scanf("%d", &_);
    //    while(_--) solve();
    
        solve();
    
        return 0;
    }
  • 相关阅读:
    C语言第0次作业
    c语言博客作业02循环结构
    C语言博客作业04数组
    存储过程,函数参数默认值的一些问题
    路线查询
    C# 猜数字
    使用 Ext.Net TreePanel,TabPanel控件 布局
    SQL SERVER 2005 动态行转列SQL
    CROSS APPLY 和OUTER APPLY 的区别
    处理表重复记录(查询和删除)
  • 原文地址:https://www.cnblogs.com/Willems/p/13619506.html
Copyright © 2011-2022 走看看