bzoj4149: [AMPPZ2014]Global Warming
头都烂了怎么头疼啊
考虑先做出对于一个位置以它作为唯一最小值的最远区间,这个可以单调栈上二分搞出来
那么对于一个位置这个区间而言,一定是选择这个区间的最大数是作为最终的唯一最大数最优的
为什么呢?我们可以把区间起止和区间之中的最大数下标弄出来,那么当前位置一定位于某两个弄出来的编号之间,其他数的答案不会大于这个区间大小,而假如是最大数除了包含这个区间以外还可以向一边拓展直到遇到下一个最大数
那么二分找出这两个编号就好了,RMQ上个st表
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> #define qq(o,l,x) upper_bound(o+1,o+l+1,x)-o-1 using namespace std; const int _=1e2; const int maxn=5*1e5+_; const int fbin=30; int n,a[maxn],lslen,ls[maxn]; int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*f; } //--------------------------------------def------------------------------------------ struct stack { int top,sta[maxn],d[maxn]; stack(){} void clear(int k){top=0;} void push(int p,int x) { while(top>=1&&d[top]>=x)top--; sta[++top]=p;d[top]=x; } int findmner(int x){return sta[qq(d,top,a[x])];} }; //~~~~~~~~stack~~~~~~~~~ int Bin[fbin],Log[maxn],f[fbin][maxn],d[fbin][maxn]; void initst() { Bin[0]=1;for(int i=1;i<=30;i++)Bin[i]=Bin[i-1]*2; Log[1]=0;for(int i=2;i<=n; i++)Log[i]=Log[i/2]+1; for(int i=1;i<=n;i++)f[0][i]=a[i]; for(int j=1;Bin[j]<=n;j++) for(int i=1;i+Bin[j]-1<=n;i++) f[j][i]=max(f[j-1][i],f[j-1][i+Bin[j-1]]), d[j][i]=max(d[j-1][i],d[j-1][i+Bin[j-1]]); } int RMQ(int x,int y) { int k=Log[y-x+1]; return max(f[k][x],f[k][y-Bin[k]+1]); } //~~~~~~~~RMQ~~~~~~~~~~~ //--------------------------------------data structure----------------------------------------- int mnL[maxn],mnR[maxn];//作为唯一最小的区间 stack up;vector<int>vec[maxn]; int main() { freopen("26.in","r",stdin); freopen("a.out","w",stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(),ls[++lslen]=a[i]; sort(ls+1,ls+lslen+1); lslen=unique(ls+1,ls+lslen+1)-ls-1; for(int i=1;i<=n;i++) { a[i]=lower_bound(ls+1,ls+lslen+1,a[i])-ls; vec[a[i]].push_back(i); } initst(); up.clear(0),up.push(0,-(1<<30)); for(int i=1;i<=n;i++) mnL[i]=up.findmner(i)+1,up.push(i,a[i]); up.clear(0),up.push(n+1,-(1<<30)); for(int i=n;i>=1;i--) mnR[i]=up.findmner(i)-1,up.push(i,a[i]); int ans=0,ll; for(int i=1;i<=n;i++) { int p=RMQ(mnL[i],mnR[i]); if(vec[p].front()<=i) { int u=upper_bound(vec[p].begin(),vec[p].end(),i)-vec[p].begin()-1; int L=mnL[i],R=mnR[i]; if(u!=0)L=max(L,vec[p][u-1]+1); if(u!=vec[p].size()-1)R=min(R,vec[p][u+1]-1); if(R-L+1>ans || R-L+1==ans&&ll>L )ans=R-L+1,ll=L; } if(vec[p].back()>=i) { int u=lower_bound(vec[p].begin(),vec[p].end(),i)-vec[p].begin(); int L=mnL[i],R=mnR[i]; if(u!=0)L=max(L,vec[p][u-1]+1); if(u!=vec[p].size()-1)R=min(R,vec[p][u+1]-1); if(R-L+1>ans || R-L+1==ans&&ll>L )ans=R-L+1,ll=L; } } printf("%d %d\n",ans,ll); return 0; }
pain and happy in the cruel world.