[51nod1502]苹果曼和纸
苹果曼有很大的一张纸。这张纸的形状是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 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #include<cstdlib> 8 #define ll long long 9 #define ull unsigned long long 10 #define ui unsigned int 11 //#define d double 12 #define ld long double 13 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<j;i++,j--)add(j,get(i)); 48 stpos+=p;rest-=p; 49 }else{ 50 for(i=stpos-(p<<1)+1,j=stpos;i<j;i++,j--)add(i,get(j)); 51 stpos-=p;rest-=p; 52 } 53 else 54 if(!rev){ 55 p=rest-p; 56 for(i=stpos+rest-1,j=i-(p<<1)+1;j<i;j++,i--)add(j,get(i)); 57 rev=1,stpos=stpos+rest-1-p;rest-=p; 58 }else{ 59 p=rest-p; 60 for(j=stpos-rest+1,i=j+(p<<1)-1;j<i;j++,i--)add(i,get(j)); 61 rev=0,stpos=stpos-rest+1+p;rest-=p; 62 } 63 }else{ 64 l=read(),r=read()-1; 65 if(!rev)printf("%d\n",query(stpos+l,stpos+r)); 66 else printf("%d\n",query(stpos-r,stpos-l)); 67 } 68 // printf(" rest:%d st:%d rev:%d\n",rest,stpos,rev); 69 // for(i=1;i<=rest;i++)printf(" %d",get(stpos+(!rev?i-1:-i+1)));puts(""); 70 } 71 }