记录编号 83899 评测结果 AAAAAAAAAA
题目名称 [NOIP 2013]积木大赛 最终得分 100
用户昵称 GravatarChenyao2333 是否通过 通过
代码语言 C++ 运行时间 0.297 s
提交时间 2013-12-07 19:53:35 内存使用 10.23 MiB
显示代码纯文本
#include<stdio.h>
#include<queue>
using std::queue;

const int MAXN=100000+10;

void open(){
	freopen("BlockNOIP2013.in","r",stdin);
	freopen("BlockNOIP2013.out","w",stdout);
}

void close(){
	fclose(stdin);
	fclose(stdout);
}

struct qujian{
	int a,b;
	qujian(int i,int j){
		a=i;
		b=j;
	}
};

struct node{
	int a,b;
	int m;
	int num;
	int lazy;
}tree[MAXN*5];

inline int mid(int a,int b){return (a+b)/2;}
inline int parent(int i){return i/2;}
inline int left(int i){return 2*i;}
inline int right(int i){return 2*i+1;} 
inline int min(int a,int b){return a>b?b:a;}

int hi[MAXN]={0};
int n;
queue<qujian> wait_slove;
queue<int> zero;

void read(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&hi[i]);
}


int build_tree(int i,int a,int b){
	node &t=tree[i];
	t.a=a;t.b=b;
	t.m=mid(a,b);
	t.lazy=0;
	if(a==b){
		t.num=hi[a];
		return t.num;
	}
	t.num=min(build_tree(left(i),a,t.m),build_tree(right(i),t.m+1,b));
	return t.num;
}

void up_lazy(int i){
     node &t=tree[i];
     if(left(i)<MAXN*5){
     tree[left(i)].num-=t.lazy;
     tree[left(i)].lazy+=t.lazy;
     }
         if(right(i)<MAXN*5){
     tree[right(i)].num-=t.lazy;
     tree[right(i)].lazy+=t.lazy;
     }
     t.lazy=0;
}

int get_min(int i,int a,int b){
	node &t=tree[i];
	
	up_lazy(i);
	
	if(t.a==t.b)return t.num;
	if(a>t.m)return get_min(right(i),a,b);
	if(b<=t.m)return get_min(left(i),a,b);
		
	return min( get_min(left(i),a,t.m) , get_min(right(i),t.m+1,b) );
}

void tree_eul(int i,int a,int b,int m){
	node &t=tree[i];
	t.num-=m;//gengxin
	up_lazy(i);//xia mian dou jian
	if((t.a==a && t.b==b))
    {
               t.lazy=m;
               return ;
    }
    
	if(a>t.m){
		tree_eul(right(i),a,b,m);
		return ;
	}
	if(b<=t.m){
		tree_eul(left(i),a,b,m);
		return ;
	}
	
	tree_eul(left(i),a,t.m,m);
	tree_eul(right(i),t.m+1,b,m);
}

void get_zero(int i,int a,int b){
	node &t=tree[i];
	up_lazy(i);
	if(t.a==t.b){
		if(t.num<=0)zero.push(a);
		return ;
	};
	if(t.num>0)return;
	if(a>t.m){
		get_zero(right(i),a,b);
		return ;
	}
	if(b<=t.m){
		get_zero(left(i),a,b);
		return ;
	}
	get_zero(left(i),a,t.m);
	get_zero(right(i),t.m+1,b);
}
	
void inc_qujian(int a,int b){
	int t_l;
	if(zero.empty())return ;
	int t=zero.front();
	zero.pop();
	if(t-1>=a)wait_slove.push(qujian(a,t-1));
	t_l=t;
	
	while(!zero.empty()){
		t=zero.front();
		zero.pop();
		if(t-1>=t_l+1){
			wait_slove.push(qujian(t_l+1,t-1));
		}
		t_l=t;
	}
	if(b>=t_l+1)wait_slove.push(qujian(t_l+1,b));
}

int solve(){
	wait_slove.push(qujian(1,n));
	int ans=0;
	while(!wait_slove.empty()){
		qujian q=wait_slove.front();
		wait_slove.pop();
		
		//printf("%d %d\n",q.a,q.b);
		
		int m=get_min(1,q.a,q.b);
		if(m){
			ans+=m;
			tree_eul(1,q.a,q.b,m);
		}
		
		while(!zero.empty())zero.pop();
			
		get_zero(1,q.a,q.b);
		inc_qujian(q.a,q.b);
	}
	return ans;
}
int main(){
	open();
	read();
	build_tree(1,1,n);
	int ans=solve();
	printf("%d",ans);
	close();
	return 0;
}