思路:先用splay处理出弹珠序列,然后就是斜率优化了
首先有f[i]=-a[i]*p[j]+q[j]
稍微变形得q[j]=a[i]*p[j]+f[i]
用单调栈维护上凸壳,询问时二分,然后就没有然后了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define max(a,b) a>b?a:b #define ll long long const int maxn=400010,inf=(int)1e9; const double eps=1e-9; using namespace std; int n,m,a[maxn],cnt,top,q[maxn];ll f[maxn];char op[10],ch; struct node{ll x,y;}p[maxn]; void read(int &x){ for (ch=getchar();!isdigit(ch);ch=getchar()); for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); } struct Spy{ int fa[maxn],c[maxn][2],size[maxn],val[maxn],root,tot; int newnode(int v){val[++tot]=v,size[tot]=1,fa[tot]=c[tot][0]=c[tot][1]=0;return tot;} void clear(){tot=c[1][1]=size[1]=2,root=fa[2]=size[2]=1;} int which(int x){return c[fa[x]][1]==x;} void update(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;} void rotate(int x){ int y=fa[x],z=fa[y],nx=which(x),ny=which(y); fa[c[x][!nx]]=y,c[y][nx]=c[x][!nx]; fa[x]=z;if (z) c[z][ny]=x; fa[y]=x,c[x][!nx]=y;update(y); } void splay(int x){ while (fa[x]){ if (!fa[fa[x]]) rotate(x); else if (which(fa[x])==which(x)) rotate(fa[x]),rotate(x); else rotate(x),rotate(x); } root=x,update(x); } int getpos(int rank){ for (int x=root;;){ //printf("rank%d %d %d %d\n",rank,size[root],size[c[root][0]],size[c[root][1]]); if (rank<size[c[x][0]]+1) x=c[x][0]; else if (rank==size[c[x][0]]+1) return x; else rank-=(size[c[x][0]]+1),x=c[x][1]; } } void modify(int rank,int v){int x=getpos(rank);val[x]=v,splay(x);} void insert(int rank,int v){ int x=getpos(rank);splay(x); int xx=c[x][1];for (;c[xx][0];xx=c[xx][0]) ; c[xx][0]=newnode(v),fa[tot]=xx,splay(tot); } void get(int x){ if (c[x][0]) get(c[x][0]); if (x!=1&&x!=2) a[++cnt]=val[x]; if (c[x][1]) get(c[x][1]); } }T; double slope(int i,int j){ if (i==0||j==0) return inf; if (i==inf||j==inf) return -inf; return 1.0*(p[i].y-p[j].y)/(double)(p[i].x-p[j].x); } void work(){ q[0]=0,q[top=1]=1,q[top+1]=inf; for (int i=2;i<=n;i++){ int l=1,r=top,mid=(l+r)>>1; while (1){ if (slope(q[mid-1],q[mid])+eps>=a[i]&&slope(q[mid],q[mid+1])<=eps+a[i]){break;} if (slope(q[mid],q[mid+1])>eps+a[i]) l=mid+1; else r=mid-1; mid=(l+r)>>1; } f[i]=-p[q[mid]].x*a[i]+p[q[mid]].y; while (top>1&&slope(q[top-1],q[top])<slope(q[top],i)) --top; q[++top]=i;q[top+1]=inf; } for (int i=2;i<=n;i++) printf("%lld\n",max(0,f[i])); } int main(){ scanf("%d%d",&n,&m),T.clear(); for (int i=1,x,y;i<=m;i++){ scanf("%s",op);read(x),read(y); if (op[0]=='I') T.insert(x+1,y); else T.modify(x+2,y); } T.get(T.root); //for (int i=1;i<=cnt;i++) printf("%d\n",a[i]); for (int i=1,x,y;i<=n;i++) read(x),read(y),p[i].x=x,p[i].y=y; work(); return 0; }