1. 程式人生 > 其它 >#樹狀陣列#CF461C Appleman and a Sheet of Paper

#樹狀陣列#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;
}