zoukankan      html  css  js  c++  java
  • Codeforces 526F. Pudding Monsters 题解

    题目链接:F. Pudding Monsters

    题目大意:洛谷


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

    单调栈维护最大最小值,然后用线段树维护(maxn-minn-len+1)的值,最后的个数就是 0 的个数,因为单调栈中每一个元素只会出入栈一次,所以时间复杂度(O(nlog 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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    java 8 stream sql left join =》 jooq & Flink & Scala
    Maven error: lambda expressions are not supported in -source 1.7
    error C2039: 'SetWindowTextA' : is not a member of 'CString'
    循环队列(循环数组)中元素个数的计算
    数据结构之堆
    理解C语言声明的优先级规则
    内联汇编中的asm和__asm__
    程序启动时的堆栈
    局部变量与堆栈
    BCD码干什么用的?
  • 原文地址:https://www.cnblogs.com/withhope/p/13646956.html
Copyright © 2011-2022 走看看