Codeforces Round #263 (Div. 2) E

E. Appleman and a Sheet of Paper


        题意:一张纸,有n个单位长度,有两种操作,一是从左往右折叠到指定位置,二是求一个区间内有多少个单位长度的纸。

        思路:树状数组。操作一是区间更新,操作二是区间查询。区间更新做不到,只能对区间内每个点进行更新,区间更新需要O(q*n*log(n)),看似会超时,其实不然,因为可以折叠的程度是有限的,总复杂度实际上是O(n*log(n))。

        还有个问题,如果像题目那样每次从左往右折叠,纸的范围会大大超过其长度,处理办法是根据折叠的位置,选择正向折叠还是反向折叠,这样纸张就不会跑出n的范围了。


#include <iostream>      
#include <stdio.h>      
#include <cmath>      
#include <algorithm>      
#include <iomanip>      
#include <cstdlib>      
#include <string>      
#include <memory.h>      
#include <vector>      
#include <queue>      
#include <stack>      
#include <map>    
#include <set>    
#include <ctype.h>      
#define INF 1000000010  
#define ll long long  
#define max3(a,b,c) max(a,max(b,c))  
#define MAXN 100010  

using namespace std;

int n,Q;
int a[100010];
int c[100010];

inline int lowbit(int x){
	return x&(-x);
}

inline int update(int x,int num){
	
	while(x<=n){
		c[x]+=num;
		x+=lowbit(x);
	}
}

inline int sum(int end){
	int re=0;
	while(end){
		re+=c[end];
		end-=lowbit(end);
	}
	return re;
}

int main(){
	
	while(cin>>n>>Q){
		int curlen=n;
		int curs=1;
		for(int i=1;i<=n;i++){
			a[i]=1;
			c[i]=lowbit(i);
		}
		bool b=true;
		for(int q=0;q<Q;q++){
			int type;
			scanf("%d",&type);
			
			if(type==1){ 
				int p;
				scanf("%d",&p);
				
				bool b2=(p<=curlen/2);
				
				if( !(b^b2) ){//正叠 
					if(!b2)p=curlen-p;
					for(int i=0;i<p;i++){
						update(curs+p+i,a[curs+p-i-1]);
						update(curs+p-i-1,-a[curs+p-i-1]);
						a[curs+p+i]+=a[curs+p-i-1];
						a[curs+p-i-1]=0;
					} 
					
					if(!b2)b=!b;
					curs+=p;
					curlen=max(p,curlen-p);
					
				}else{
					if(!b2)p=curlen-p;
					for(int i=0;i<p;i++){
						update(curs+curlen-1-(p+i),a[curs+curlen-1-(p-i-1)]);
						update(curs+curlen-1-(p-i-1),-a[curs+curlen-1-(p-i-1)]);
						a[curs+curlen-1-(p+i)]+=a[curs+curlen-1-(p-i-1)];
						a[curs+curlen-1-(p-i-1)]=0;
					}
					if(!b2)b=!b;
					curlen=max(p,curlen-p);
				}
			}else{
				int l,r;
				scanf("%d%d",&l,&r);
				
				int ans=0;
				if(b){
					
					ans=sum(curs+r-1)-sum(curs+l-1);
				}else{
				
					ans=sum(curs+curlen-1-l)-sum(curs+curlen-r-1);
				}
				printf("%d\n",ans);
			}
			
		}
	}
	return 0;
}


你可能感兴趣的:(树状数组,codeforces)