1401F - Reverse and Swap(线段树 翻转所有2^k子区间)

http://codeforces.com/problemset/problem/1401/F

题意:

在这里插入图片描述
解析:

弄一个全局的int:rev来记录所有K的是否翻转(rev与rev之间满足交换律),然后 s w a p ( k ) → r e v e r s e ( k + 1 ) , r e v e r s e ( k ) swap(k)\to reverse(k+1),reverse(k) swap(k)reverse(k+1),reverse(k)

查询和单点修改的时候根据rev来转换一下坐标即可。

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-09-07-09.02.24
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define LD long double
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=(1<<18)+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define root int rt,int l,int r
#define lson ls,l,mid
#define rson rs,mid+1,r

int n,num,q;
LL a[maxn];
LL tr[maxn<<2];
int rev;
void build(root){
    if(l==r)
        tr[rt]=a[l];
    else{
        build(lson);
        build(rson);
        tr[rt]=tr[ls]+tr[rs];
    }
}

void update(root,int level,int pos,LL val){
    if(l==r){
        tr[rt]=val;
        return;
    }
    if(rev&1<<level){
        pos=l+r-pos;
    }
    if(pos<=mid)update(lson,level-1,pos,val);
    else update(rson,level-1,pos,val);
    tr[rt]=tr[ls]+tr[rs];
}

LL query(root,int level,int L,int R){
    if(l>=L&&r<=R){
        return tr[rt];
    }
    if(rev&1<<level){
        L=l+r-L;
        R=l+r-R;
        swap(L,R);
    }
    LL ans=0;
    if(L<=mid)
        ans=query(lson,level-1,L,R);
    if(R>mid)
        ans+=query(rson,level-1,L,R);
    return ans;
}

void Print(){
    return;
    rep(i,1,num)
        printf("%lld%c",query(1,1,num,n,i,i)," \n"[i==num]);
}

int main(){
    n=rd,num=1<<n,q=rd;
    rep(i,1,num)
        a[i]=rd;
    build(1,1,num);
    while(q--){
        int op=rd;
        if(op==1){
            int pos=rd,val=rd;
            update(1,1,num,n,pos,val);
            Print();
        }
        else if(op==2){
            int k=rd;
            rev^=1<<k;
            Print();
        }
        else if(op==3){
            int k=rd;
            rev^=1<<k;
            rev^=1<<k+1;
            Print();
        }
        else{
            int l=rd,r=rd;
            printf("%lld\n",query(1,1,num,n,l,r));
        }
    }
    return 0;
}
/*_________________________________________________________end*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值