Codeforces 526F. Pudding Monsters 题解

题目链接:F. Pudding Monsters

题目大意:洛谷


题解:将平面映射到序列,即令\(a_x=y\),那么问题转换为求连续段个数。

单调栈维护最大最小值,然后用线段树维护\(maxn-minn-len+1\)的值,最后的个数就是 0 的个数,因为单调栈中每一个元素只会出入栈一次,所以时间复杂度\(O(n\log n)\)

代码:

#include <cstdio>
int min(int a,int b){
	return a<b?a:b;
}
typedef long long ll;
const int Maxn=300000;
int n;
int a[Maxn+5];
int st_1[Maxn+5],top_1;
int st_2[Maxn+5],top_2;
struct Segment_Node{
	int lazy;
	int minn,num;
}seg[Maxn<<2|5];
void push_up(int root){
	seg[root].minn=min(seg[root<<1].minn,seg[root<<1|1].minn);
	seg[root].num=0;
	if(seg[root].minn==seg[root<<1].minn){
		seg[root].num+=seg[root<<1].num;
	}
	if(seg[root].minn==seg[root<<1|1].minn){
		seg[root].num+=seg[root<<1|1].num;
	}
}
void push_down(int root){
	if(seg[root].lazy==0){
		return;
	}
	seg[root<<1].lazy+=seg[root].lazy;
	seg[root<<1].minn+=seg[root].lazy;
	seg[root<<1|1].lazy+=seg[root].lazy;
	seg[root<<1|1].minn+=seg[root].lazy;
	seg[root].lazy=0;
}
void build(int root=1,int left=1,int right=n){
	seg[root].lazy=0;
	if(left==right){
		seg[root].minn=left;
		seg[root].num=1;
		return;
	}
	int mid=(left+right)>>1;
	build(root<<1,left,mid);
	build(root<<1|1,mid+1,right);
	push_up(root);
}
void update(int l,int r,int a,int root=1,int left=1,int right=n){
	if(l>right||r<left){
		return;
	}
	if(l<=left&&r>=right){
		seg[root].lazy+=a;
		seg[root].minn+=a;
		return;
	}
	push_down(root);
	int mid=(left+right)>>1;
	update(l,r,a,root<<1,left,mid);
	update(l,r,a,root<<1|1,mid+1,right);
	push_up(root);
}
int query(int l,int r,int root=1,int left=1,int right=n){
	if(l>right||r<left){
		return 0;
	}
	if(l<=left&&r>=right){
		return seg[root].minn==0?seg[root].num:0;
	}
	push_down(root);
	int mid=(left+right)>>1;
	return query(l,r,root<<1,left,mid)+query(l,r,root<<1|1,mid+1,right);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		a[x]=y;
	}
	build();
	ll ans=0;
	for(int i=1;i<=n;i++){
		update(1,n,-1);
		while(top_1>0&&a[st_1[top_1]]<a[i]){
			update(st_1[top_1-1]+1,st_1[top_1],a[i]-a[st_1[top_1]]);
			top_1--;
		}
		while(top_2>0&&a[st_2[top_2]]>a[i]){
			update(st_2[top_2-1]+1,st_2[top_2],a[st_2[top_2]]-a[i]);
			top_2--;
		}
		ans+=query(1,i);
		st_1[++top_1]=i;
		st_2[++top_2]=i;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2020-09-10 17:25  with_hope  阅读(171)  评论(0编辑  收藏  举报