zoukankan      html  css  js  c++  java
  • BZOJ4311 向量(线段树分治+三分)

      由点积的几何意义(即投影)可以发现答案一定在凸壳上,并且投影的变化是一个单峰函数,可以三分。现在需要处理的只有删除操作,线段树分治即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 200010
    #define ll long long 
    int n,m,t;
    int L[N<<2],R[N<<2],size[N<<2];
    struct point
    {
        int x,y,s;
        ll operator *(const point&a) const
        {
            return 1ll*x*a.x+1ll*y*a.y;
        }
        bool operator <(const point&a) const
        {
            return x<a.x;
        }
    }a[N],q[N];
    bool check(point a,point b,point c)
    {
        return 1ll*(a.y-b.y)*(c.x-b.x)>1ll*(c.y-b.y)*(a.x-b.x);
    }
    vector<point> tree[N<<2];
    void build(int k,int l,int r)
    {
        L[k]=l,R[k]=r;
        if (l==r) return;
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    void ins(int k,int l,int r,point x)
    {
        if (L[k]==l&&R[k]==r) {tree[k].push_back(x);return;}
        int mid=L[k]+R[k]>>1;
        if (r<=mid) ins(k<<1,l,r,x);
        else if (l>mid) ins(k<<1|1,l,r,x);
        else ins(k<<1,l,mid,x),ins(k<<1|1,mid+1,r,x);
    }
    void make(int k)
    {
        sort(tree[k].begin(),tree[k].end());
        int s=tree[k].size(),t=-1;
        for (int i=0;i<s;i++)
        {
            while (t>=0&&tree[k][i].y>tree[k][t].y) t--;
            while (t>0&&check(tree[k][t-1],tree[k][t],tree[k][i])) t--;
            tree[k][++t]=tree[k][i];
        }
        size[k]=t;
        if (L[k]==R[k]) return;
        make(k<<1),make(k<<1|1);
    }
    ll calc(int k,point x)
    {
        if (size[k]==-1) return 0;
        int l=0,r=size[k];
        while (l+2<r)
        {
            int mid1=l+(r-l)/3,mid2=r-(r-l)/3;
            if (x*tree[k][mid1]>x*tree[k][mid2]) r=mid2;
            else l=mid1;
        }
        ll ans=0;
        for (int i=l;i<=r;i++) ans=max(ans,x*tree[k][i]);
        return ans;
    }
    ll query(int k,int p,point x)
    {
        ll t=calc(k,x);
        if (L[k]==R[k]) return t;
        int mid=L[k]+R[k]>>1;
        if (p<=mid) return max(t,query(k<<1,p,x));
        else return max(t,query(k<<1|1,p,x));
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4311.in","r",stdin);
        freopen("bzoj4311.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        build(1,1,n);
        for (int i=1;i<=n;i++)
        {
            int op=read();
            if (op==1) t++,a[t].x=read(),a[t].y=read(),a[t].s=i;
            else if (op==3) m++,q[m].x=read(),q[m].y=read(),q[m].s=i;
            else
            {
                int x=read();
                ins(1,a[x].s,i,a[x]);
                a[x].x=a[x].y=0;
            }
        }
        for (int i=1;i<=t;i++)
        if (a[i].x) ins(1,a[i].s,n,a[i]);
        make(1);
        for (int i=1;i<=m;i++) printf(LL,query(1,q[i].s,q[i]));
        return 0;
    }
  • 相关阅读:
    C++设计模式-Bridge桥接模式
    解决VS2010打开Web页面时经常由于内存较低而导致VS2010自动关闭的问题
    Js继承小结
    MAC上的包管理利器
    Objective-C的hook方案(一): Method Swizzling
    OleContainer操作Excel以二进制方式读写数据库
    复制文件时,如何显示进度条(使用TFileStream一点一点读,或者使用BlockRead,并插入application.ProcessMessages)
    ADO异步查询显示进度条
    D2010 RTTI + Attribute 简单实现ORM
    Delphi默认窗体随想
  • 原文地址:https://www.cnblogs.com/Gloid/p/9852454.html
Copyright © 2011-2022 走看看