苹果曼有很大的一张纸。这张纸的形状是1×n的长方形。你的任务是帮助苹果曼来折叠这一张纸。有一些操作,这些操作有如下两个种形式:
1. 把这张纸在第pi个位置对折。经过对折后,左边的1×pi部分会盖到右边的1×([当前纸片宽度]-pi)上面。 2. 询问在如果把距离左端li以内的剪掉,距离左端ri以外的也剪掉,那么还剩下多少纸片的长度。 看样例,可以更好的解理这个问题。第一次折叠之后,纸片的宽度变成了4,第二次折叠,纸片的宽度变成了2。
Input
单组测试数据。 第一行有两个整数n和q (1≤n≤10^5; 1≤q≤10^5),表示纸片的宽度和询问数目。 接下来q行的形式是如下之一: · "1 pi" (1≤pi<[当前纸片宽度]) — 第一类操作。 · "2 li ri" (0≤li<ri≤[当前纸片宽度]) — 第二类操作。 Output 对于第二类操作,输出答案。Input示例
7 4 1 3 1 2 2 0 1 2 1 2 Output示例 4 3
维护一下每个位置上有多少层纸,每次翻折的时候,只翻较短的一部分(所以得记一下当前的方向),那么总共最多只会有n个位置被翻到别的位置上。
主要是记方向、计算实际位置很麻烦...
我直接分类讨论。。当前维护的是否是翻转后的、当前翻折操作是否是否会导致翻转,总共四类。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #define ll long long 9 #define ull unsigned long long10 #define ui unsigned int11 //#define d double12 #define ld long double13 const int maxn=100233,modd=1000000007;14 int t[maxn];15 int i,j,k,n,m;16 17 int ra,fh;char rx;18 inline int read(){19 rx=getchar(),ra=0,fh=1;20 while(rx<'0'&&rx!='-')rx=getchar();21 if(rx=='-')fh=-1,rx=getchar();22 while(rx>='0')ra=ra*10+rx-48,rx=getchar();return ra*fh;23 }24 25 inline void add(int x,int V){ while(x<=n)t[x]+=V,x+=x&-x;}26 inline int get(int x){27 int sm=0,x1=x-1;28 while(x)sm+=t[x],x-=x&-x;29 while(x1)sm-=t[x1],x1-=x1&-x1;30 return sm;31 }32 inline int query(int l,int r){33 int sm=0;34 while(r)sm+=t[r],r-=r&-r;35 l--;while(l)sm-=t[l],l-=l&-l;return sm;36 }37 38 int main(){39 n=read(),m=read();register int i,j;40 for(i=1;i<=n;i++){t[i]++;if(i+(i&-i)<=n)t[i+(i&-i)]+=t[i];}41 int l,r,stpos=1,rest=n,p;bool rev=0;42 while(m--){43 if(read()==1){44 p=read();45 if((p<<1)<=rest)46 if(!rev){47 for(i=stpos,j=stpos+(p<<1)-1;i