#树状数组#CF461C Appleman and a Sheet of Paper

题目传送门


分析

可以发现往左翻太多相当于往右翻一点,所以如果翻的位置超过一半那么打一个取反标记再另一边翻转,

用树状数组维护当前厚度,时间复杂度 \(O(n\log^2 n)\)


代码

#include <cstdio>
#include <cctype>
using namespace std;
int n,Q,L,R,c[100011],you;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
void update(int x,int y){
	for (;x<=n;x+=-x&x) c[x]+=y;
}
int query(int x){
	int ans=0;
	for (;x;x-=-x&x) ans+=c[x];
	return ans;
}
int main(){
	n=iut(),Q=iut(),L=1,R=n;
	for (int i=1;i<=n;++i) c[i]=-i&i;
	for (int i=1;i<=Q;++i){
		int opt=iut(),half=(R-L+1)>>1;
		if (opt==1){
			int x=iut();
			if (you){
				if (x<=half){
					for (int i=R;i>R-x;--i){
						int t=query(i)-query(i-1);
						update(R-x-(i-1-(R-x)),t);
					}
					R-=x;
				}else{
					x=R-L+1-x;
					for (int i=L;i<L+x;++i){
						int t=query(i)-query(i-1);
						update(L+x+((L+x)-i-1),t);
					}
					you^=1,L+=x;
				}
			}else{
				if (x<=half){
					for (int i=L;i<L+x;++i){
						int t=query(i)-query(i-1);
						update(L+x+((L+x)-i-1),t);
					}
					L+=x;
				}else{
					x=R-L+1-x;
					for (int i=R;i>R-x;--i){
						int t=query(i)-query(i-1);
						update(R-x-(i-1-(R-x)),t);
					}
					you^=1,R-=x;
				}
			}
		}else{
			int l=iut(),r=iut();
			if (you) print(query(R-l)-query(R-r));
			    else print(query(L+r-1)-query(L+l-1));
			putchar(10);
		}
	}
	return 0;
}
posted @ 2022-03-22 21:03  lemondinosaur  阅读(32)  评论(0编辑  收藏  举报