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\n";
#else
    const char LL[]="%lld\n";
#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;
}

 

posted @ 2018-10-25 20:36  Gloid  阅读(199)  评论(0编辑  收藏  举报