zoukankan      html  css  js  c++  java
  • bzoj4172: 弹珠


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


  • 相关阅读:
    并发编程
    网络与WEB 编程
    包和模块
    元编程
    类和对象
    【算法题 14 LeetCode 147 链表的插入排序】
    剑指offer面试54题
    剑指offer 面试51题
    剑指offer 面试3题
    剑指offer 面试52题
  • 原文地址:https://www.cnblogs.com/thythy/p/5493581.html
Copyright © 2011-2022 走看看