CF 678F Lena and Queries

来源:互联网 发布:js攻击脚本代码 编辑:程序博客网 时间:2024/05/22 11:51

一个空集,有n(30w)个操作:
1)集合加入对(a,b)(109a,b109)
2)移除ith操作加入的对
3)给出q(109q109),对于集合中所有的(x,y),求x·q+y的最大值。
PS:这里的集合应该允许同一元素出现多次,或者加入时间也包含在元素的信息中。
分治+凸壳
PS:有对 HDU 5390 tree 的线段树的一点改进。

#include <set>#include <cmath>#include <queue>#include <stack>#include <cstdio>#include <bitset>#include <cassert>#include <cstring>#include <complex>#include <iostream>#include <algorithm>#define pi acos(-1)#define inf (1<<30)#define INF (1ll<<62)#define y1 bflaisfnmasf#define y2 fsafgmalg#define tm afnsjkf#define j1 sfakf#define j2 fasndfkas#define fi first#define se second#define CLR(x,f) memset(x,f,sizeof(x))#define CPY(x,y) memcpy(x,y,sizeof(x))#define prt(x) cout<<#x<<":"<<x<<" "#define prtn(x) cout<<#x<<":"<<x<<endl#define huh(x) printf("--------case(%d)--------\n",x)#define travel(x) for(Edge *e=h[x];e;e=e->n)#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int M=3e5+4;template<class T>void Max(T &x,T y){    if(x<y)x=y;}//nice!typedef long long ll;typedef double doub;struct Point{    ll x,y;    bool operator<(const Point &a)const{        return x==a.x?y<a.y:x<a.x;    }    Point operator-(const Point &a)const{        return (Point){x-a.x,y-a.y};    }    ll operator*(const Point &a)const{        return x*a.x+a.y*y;    }    ll operator^(const Point &a)const{        return x*a.y-a.x*y;    }//cross(a,b)?}po[M],s[M],g[M];struct Pt{    int l,r;    Point p;}p[M];struct Qr{    int t;ll x;}q[M];int conpoly(int n){    int w=0;    sort(s+1,s+n+1);    for(int i=1;i<=n;i++){        while(w>1&&(s[w]-s[w-1]^s[i]-s[w-1])>=0)w--;        s[++w]=s[i];    }    return w;}//仅保留凸包 void calc(int n){    for(int i=1;i<n;i++){        g[i]=s[i+1]-s[i];        g[i].y=-g[i].y;    }}bool cmp(Point a,Point b){    return a.y*b.x<b.y*a.x;}ll query(ll x,int n){    if(n==1)return x*s[1].x+s[1].y;    int p=lower_bound(g+1,g+n,(Point){1,x},cmp)-g;    ll res=-INF;    for(int i=-1;i<=1;i++)        if(p+i>0&&p+i<=n)            Max(res,x*s[p+i].x+s[p+i].y);    //nice!//  ll tmp=-INF;//  for(int i=1;i<=n;i++)//      Max(tmp,x*s[i].x+s[i].y);//  assert(tmp==res);    return res;}ll ans[M];void solve(int n,int m,int l,int r){    if(!n||!m||l>r)return;    int w=0;    for(int i=0;i<n;i++)        if(p[i].l<=l&&r<=p[i].r)            s[++w]=p[i].p;    if(w>0){        w=conpoly(w);calc(w);        for(int i=0;i<m;i++)            Max(ans[q[i].t],query(q[i].x,w));    }    if(l==r)return;    int mid=l+r>>1,w0,w1;    w0=w1=0;    for(int i=0;i<n;i++)        if(p[i].l<=mid&&!(p[i].l<=l&&r<=p[i].r))            swap(p[w0++],p[i]);    for(int i=0;i<m;i++)        if(q[i].t<=mid)            swap(q[w1++],q[i]);    solve(w0,w1,l,mid);    w0=w1=0;    for(int i=0;i<n;i++)        if(p[i].r>mid&&!(p[i].l<=l&&r<=p[i].r))            swap(p[w0++],p[i]);    for(int i=0;i<m;i++)        if(q[i].t>mid)            swap(q[w1++],q[i]);    solve(w0,w1,mid+1,r);}int en[M],type[M];int main(){    int n;    scanf("%d",&n);    int w1,w2;    w1=w2=0;    for(int u,v,i=0;i<n;i++){        scanf("%d",&type[i]);        //1)Add a pair (a,b) to the set.        //2)Remove a pair added in the query number i. All queries are numbered with integers from 1 to n.        //3)For a given integer q find the maximal value x·q?+?y over all pairs (x,y) from the set.        switch(type[i]){            case 1:                scanf("%d%d",&u,&v);                po[i]=(Point){u,v};                en[i]=n-1;                break;            case 2:                scanf("%d",&u);                en[u-1]=i;                break;            case 3:                scanf("%d",&u);                q[w2++]=(Qr){i,u};                ans[i]=-INF;                break;            default:break;//        }    }    for(int i=0;i<n;i++)        if(type[i]==1)p[w1++]=(Pt){i,en[i],po[i]};    solve(w1,w2,0,n-1);    for(int i=0;i<n;i++){        if(type[i]==3){            if(ans[i]==-INF)puts("EMPTY SET");            else printf("%I64d\n",ans[i]);        }    }    return 0;}
0 0
原创粉丝点击