测试51T2:单调栈维护下凸包二分
单调栈维护凸包,并在凸包上二分的一类题。
1、本题维护的每个决策点是一个一次函数,即一条线。
2、下凸包的维护:1、斜率递增,pop掉斜率比他大的
2、交点递减,防止不优的线影响决策
3、代码自己写的,开始没看std,改不出来后看了第二个while,即交点递减,没考虑到。
这点比较好。要相信自己也能写出来。
详细见注释。
#include<bits/stdc++.h> #define F(i,a,b) for(rg int i=a;i<=b;++i) #define rg register #define LL long long #define il inline #define pf(a) printf("%lld ",a) #define phn puts("") using namespace std; #define int LL #define N 500010 int read(); int n,que; int s[N],a[N],c[N]; int min(int x,int y){return x<y?x:y;} int max(int x,int y){return x>y?x:y;} struct Q{ int x,y,id; friend bool operator <(const Q& a,const Q& b){return a.y<b.y||(a.y==b.y&&a.x<b.x);} }b[N]; int sta[N],top,ans[N]; double get(int i,int j){ return 1.0*(c[j]-c[i])/(a[i]-a[j]); } void push(int x){ while(top&&a[sta[top]]>=a[x])--top; while(top>1&&get(x,sta[top])>=get(sta[top],sta[top-1]))--top; /** 这里是凸包的维护。第二句:使交点在栈内单调递减。因为画图发现交点递减才成为凸包,否则上一条线可以去掉 如果不去掉,决策会使用上一条线,导致挡住原本更优的决策 所以下凸包的维护:1、斜率递增,pop掉斜率比他大的 2、交点递减,防止不优的线影响决策 */ sta[++top]=x; } /** 可以证明,超过边界的不合法的决策点不优*/ int solve(int x,int y){ int l=1,r=top,mid; while(l<r){ mid=l+r>>1; // if(y-sta[mid]+1>x){l=mid+1;continue;} if(get(sta[mid],sta[mid+1])>x-y)l=mid+1; else r=mid; } l=sta[l]; // pf(l);pf(x);pf(y);phn; /*if(x==100&&y==7){ F(i,1,top)pf(a[sta[i]]);phn;while(1); }*/ return s[y]-s[l]+(x-y+l)*a[l]; } signed main(){ // freopen("function2.in","r",stdin); freopen("1.out","w",stdout); n=read(); F(i,1,n)s[i]=s[i-1]+(a[i]=read()),c[i]=i*a[i]-s[i]; que=read(); F(i,1,que)b[i]=(Q){read(),read(),i}; sort(b+1,b+que+1); int p=1; while(b[p].y==1){ ans[b[p].id]=a[1]*b[p].x;++p; } sta[top=1]=1; /** s[y]0-s[i]+(x-y+i)*a[i] 先判两个端点。 */ int i,x,y; F(k,2,n){ push(k); if(top==1){ i=sta[1]; while(b[p].y==k){ ans[b[p].id]=a[k]*b[p].x; ++p; } continue; } while(b[p].y==k){ ans[b[p].id]=solve(b[p].x,k); ++p; } // push(k); } F(i,1,que)printf("%lld\n",ans[i]); } int read(){ int s=0,f=0;char ch; while(ch=getchar(),ch=='-'?f=1:0,!isdigit(ch)); for(;isdigit(ch);s=s*10+(ch^48),ch=getchar()); return f?-s:s; } /* g++ 1.cpp -g ./a.out g++ dp.cpp -g ./a.out 10 10 9 1 7 4 6 8 5 2 3 10 4 2 100 2 6 3 1 4 3 5 1 7 100 7 5 8 2 9 100 10 */
关于不合法的点一定不优的证明:
我证出来了,但是懒得写了。我要去看T3了。
Informatik verbindet dich und mich.
信息将你我连结。