思路:先用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;
}