题解CF1401F【リバースアンドスワップ】

解決策-CF1401 F \ mathrm {CF1401F}C F 1 4 0 1 F

トピックの意味

トピックポータル

S ol \ mathrm {Sol} S O L

難しいことではないdsの質問

シーケンスをラインセグメントツリー2n 2 ^ nに配置することを検討します2nの数は、ラインセグメントツリーのリーフノードの数に相当します。

1〜4 1 \シム41操作4は、2、3 2 32 3は維持するより難しい、我々は考える2/22操作、iiを想定iノードはラインセグメントツリーのddですd層(1 11ノードはnnですn層)。次に、反転操作は、下のすべてのレイヤーの左と右の息子をそれぞれ反転することと同等であるため、0〜d 0 \ simdを設定します。0レイヤーdをマークするだけです。以下のための3 33操作はd + 1 d +1と同等ですd+1層ブランディングマシンは、隣接するブロックの交換を実現できます。

マークされたレイヤーについては、逆の再帰を実行でき、残りはラインセグメントツリーの間隔の合計です。詳細については、コードの実装を参照してください。

時間の複雑さO(2 18×18)O(2 ^ {18} \ times 18)O 21 8××1 8

コード\ mathrm {Code} C O D E

const int mo=998244353;
const int N=1<<18;

int n,m,S,a[N+5],t[N*4+5],flg[21];

inline void Fix(int x,int l,int r,int p,int val,int d)
{
    
    
	if(p>r||p<l) return;
	if(l==r)
	{
    
    
		t[x]=val;
		return;
	}
	int mid=l+r>>1;
	if(flg[d]) Fix(x<<1|1,l,mid,p,val,d-1),Fix(x<<1,mid+1,r,p,val,d-1);
	else Fix(x<<1,l,mid,p,val,d-1),Fix(x<<1|1,mid+1,r,p,val,d-1);
	t[x]=t[x<<1]+t[x<<1|1];
}

inline int Ask(int x,int l,int r,int ll,int rr,int d)
{
    
    
	if(ll>r||rr<l) return 0;
	if(ll<=l&&r<=rr) return t[x];
	int mid=l+r>>1;
	int ans=0;
	if(flg[d]) ans=Ask(x<<1,mid+1,r,ll,rr,d-1)+Ask(x<<1|1,l,mid,ll,rr,d-1);//如果打上标记,那么对于左儿子要在[mid+1,r]里递归下去
	else ans=Ask(x<<1,l,mid,ll,rr,d-1)+Ask(x<<1|1,mid+1,r,ll,rr,d-1); 
	return ans;
}

signed main()
{
    
    
	io.read(n),io.read(m);
	S=(1ll<<n);
	For(i,1,S) 
	{
    
    
		io.read(a[i]);
		Fix(1,1,S,i,a[i],n);
	}
	for (;m--;)
	{
    
    
		int type,x,y;
		io.read(type);
		io.read(x);
		if((type^2)&&(type^3)) io.read(y);
		if(type==1) Fix(1,1,S,x,y,n);
		if(type==3) flg[x+1]^=1;
		if(type==2) For(i,0,x) flg[i]^=1;
		if(type==4) io.write(Ask(1,1,S,x,y,n)),puts("");
	}
	return 0;
}
			
		
	
	

おすすめ

転載: blog.csdn.net/wangyiyang2/article/details/108175961