[CodeForces - 678F] Lena and Queries 线段树维护凸包

   大致题意:

      给出三种操作

        1、往平面点集中添加一个点

        2、删除第i次添加的点

        3、给出一个q,询问平面点集中的q*x+y的最大值

  

    首先对于每个询问,可将z=q*x+y转化为y=z-q*x,即过点(x,y)的斜率为-q的最大截距,很容易发现这些点只会在上凸包上,只要在

    凸包上三分即可。

    对于插入和删除操作,对于每个点可求得其“生存周期”,即其存在于[L,R]的时间范围内。对每个点的时间区间建线段树,则每次询问的

    答案即为询问所在的区间内凸包上点中的最大值。

    

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<set>
  7 #include<map>
  8 #include<stack>
  9 #include<time.h>
 10 #include<cstdlib>
 11 #include<cmath>
 12 #include<list>
 13 using namespace std;
 14 #define MAXN 300100
 15 #define eps 1e-5
 16 #define For(i,a,b) for(int i=a;i<=b;i++)
 17 #define Fore(i,a,b) for(int i=a;i>=b;i--)
 18 #define lson l,mid,rt<<1
 19 #define rson mid+1,r,rt<<1|1
 20 #define mkp make_pair
 21 #define pb push_back
 22 #define cr clear()
 23 #define sz size()
 24 #define met(a,b) memset(a,b,sizeof(a))
 25 #define iossy ios::sync_with_stdio(false)
 26 #define fr freopen
 27 #define pi acos(-1.0)
 28 #define Vector Point
 29 const long long inf=1LL<<62;
 30 const int Mod=1e9+7;
 31 typedef unsigned long long ull;
 32 typedef long long ll;
 33 typedef pair<int,int> pii;
 34 typedef pair<ll,ll> pll;
 35 int dcmp(double x){
 36     if(fabs(x)<=eps) return 0;
 37     return x<0?-1:1;
 38 }
 39 struct Point {
 40     ll x,y;
 41     int l,r;
 42     Point(ll x=0,ll y=0) : x(x),y(y) {}
 43     Point operator - (const Point &a)const{ return Point(x-a.x,y-a.y); }
 44     Point operator + (const Point &a)const{ return Point(x+a.x,y+a.y); }
 45     Point operator * (const double &a)const{ return Point(x*a,y*a); }
 46     Point operator / (const double &a)const{ return Point(x/a,y/a); }
 47     bool operator < (const Point &a)const{    if(x==a.x) return y<a.y;return x<a.x; }
 48     bool operator == (const Point &a)const{ return dcmp(x-a.x)==0 && dcmp(y-a.y)==0; }
 49     void read() { scanf("%lld%lld",&x,&y);}
 50     void out(){cout<<"Bug: "<<x<<" "<<y<<endl;}
 51 };
 52 inline ll Cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; }
 53 inline double Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; }
 54 inline double dis(Vector a) { return sqrt(Dot(a,a)); }
 55 Point p[MAXN];
 56 pii q[MAXN];
 57 int mp[MAXN],m,n;
 58 vector<Point>T[MAXN<<2];
 59 ll ans[MAXN];
 60 Point ch[MAXN];
 61 int ty[MAXN];
 62 void Insert(int L,int R,Point pp,int l,int r,int rt){
 63     int mid=l+r>>1;
 64 //    cout<<L<<" "<<R<<" "<<l<<" "<<r<<" "<<rt<<endl;
 65     if(L<=l && r<=R) {T[rt].pb(pp);return ;}
 66 //    if(l==r) return ;
 67     if(R<=mid) Insert(L,R,pp,lson);
 68     else if(L>mid) Insert(L,R,pp,rson);
 69     else Insert(L,mid,pp,lson),Insert(mid+1,R,pp,rson);
 70 }
 71 ll Query(int x,int now){
 72     int l=0,r=m-1;
 73     while(l<r-2){
 74         int lmid=(l+l+r)/3;
 75         int rmid=(l+r+r+2)/3;
 76         if(x*ch[lmid].x+ch[lmid].y<x*ch[rmid].x+ch[rmid].y) l=lmid;
 77         else r=rmid;
 78     }
 79     For(i,l,r) ans[now]=max(ans[now],x*ch[i].x+ch[i].y);
 80 }
 81 void Down(int l,int r,int rt){
 82     int mid=l+r>>1;
 83     if(l<r){
 84         Down(lson);
 85         Down(rson);
 86     }
 87     m=0;
 88     for(int i=0;i<T[rt].sz;i++){
 89         while(m>1 && Cross(T[rt][i]-ch[m-2],ch[m-1]-ch[m-2])<=0) m--;
 90         ch[m++]=T[rt][i];
 91     }
 92     For(i,l,r){
 93         if(ty[i]==3) Query(mp[i],i);
 94     }
 95 }
 96 void solve(){
 97     cin>>n;
 98     met(mp,0);
 99     fill(ans,ans+MAXN,-inf);
100     For(i,0,n*4) T[i].clear();
101     met(p,0);
102     int ct=0,pt=0,now=0;
103     For(i,1,n){
104         scanf("%d",&ty[i]);
105         if(ty[i]==1) p[pt].read(),p[pt].l=i,p[pt].r=n,mp[i]=pt++,now++;
106         if(ty[i]==2) {scanf("%d",&m);p[mp[m]].r=i,now--;}
107         if(ty[i]==3) {scanf("%d",&mp[i]);if(now==0) ty[i]=4;}                                                                                                                            
108     }
109     sort(p,p+pt);
110     For(i,0,pt-1) Insert(p[i].l,p[i].r,p[i],1,n,1);
111     Down(1,n,1);
112     for(int i=1;i<=n;i++){
113         if(ty[i]==4) puts("EMPTY SET");
114         if(ty[i]==3) printf("%lld\n",ans[i]);
115     }
116 }
117 int main(){
118 //  fre("in.txt","r",stdin);
119     int t=1;
120     while(t--)solve();
121     return 0;
122 }
View Code

猜你喜欢

转载自www.cnblogs.com/cjbiantai/p/9379073.html