zoukankan      html  css  js  c++  java
  • [51Nod1482] 部落信号

    题意:有N个部落围成一圈,每个部落都有一个高度,如果两个部落之间的部落高度都低于这两个部落的高度,那么这两个部落则互相可见,一个部落从顺时针或逆时针方向看到另一个部落都算互相可见

    题解:

    单调栈

    一个部落从顺时针方向看到与它互相可见的部落,一定是一段连续递增的序列,逆时针同理

    这就很像单调栈的维护方式

    先把最大的点砍掉,断环为链

    然后对于每个点顺时针和逆时针的贡献都用单调栈统计一次

    最后再把最大点的贡献算一遍

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long  
    using namespace std;
    
    const int N = 1000010;
    
    int n,mx,top;
    int a[N],v[N],stk[N],same[N],bj[N],l[N],r[N];
    ll ans;
    
    int gi() {
    	int x=0,q=1; char ch=getchar();
    	while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    	if(ch=='-') q=-1;
    	while(ch>='0' && ch<='9') x=10*x+ch-'0',ch=getchar();
    	return x*q;
    }
    
    int main() {
    	n=gi();
    	for(int i=1; i<=n; i++) {
    		a[i]=gi();
    		if(!mx || a[i]>a[mx]) mx=i;
    	}
    	for(int i=mx; i<=n; i++) v[++top]=a[i];
    	for(int i=1; i<=mx-1; i++) v[++top]=a[i];
    	top=0;
    	for(int i=2; i<=n; i++) {
    		while(top && v[i]>=v[stk[top]]) top--;
    		l[i]=stk[top];
    		stk[++top]=i;
    	}
    	top=0,stk[top]=n+1;
    	for(int i=n; i>=2; i--) {
    		while(top && v[i]>=v[stk[top]]) {
    			if(v[i]==v[stk[top]]) same[i]=same[stk[top]]+1;
    			top--;
    		}
    		r[i]=stk[top];
    		stk[++top]=i;	
    	}
    	for(int i=2; i<=n; i++) {
    		if(l[i]>0) ans++;
    		if(r[i]<=n) ans++;
    		ans+=same[i];
    	}
    	mx=0;
    	for(int i=2; i<=n; i++) {
    		if(v[i]>=mx) bj[i]=1;
    		mx=max(mx,v[i]);
    	}
    	mx=0;
    	for(int i=n; i>=2; i--) {
    		if(v[i]>=mx) bj[i]=1;
    		mx=max(mx,v[i]);
    	}
    	for(int i=2; i<=n; i++) ans+=bj[i];
    	printf("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    通信中的相干与非相干
    OFDM为什么要在频域内插后做fftshift
    OFDM为什么把高频子载波作为保护频带
    辛几何
    奇文共欣赏
    6G新技术
    高扇出导致的系统异常解决方法

    线程与守护线程
    进程之间的通行
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7535720.html
Copyright © 2011-2022 走看看