cdq分治 -- CF edu13 F Lena and Queries

F. Lena and Queries

  我的第一道cdq分治,简直绝妙。。由于点会被删除,相当于每个点有一个作用区间 [l,r] 。对询问分治,每次在分治区间内求凸壳(只使用作用区间包含分治区间的那些点求),更新答案。至于每个点出现在了哪些区间,用线段树维护。

#include 

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
ll ans[maxn];
int r[maxn];

inline int getID(int l,int r){
    return (l+r)|(lstruct Point{
    ll x,y;
    Point(ll x,ll y):x(x),y(y){
    }
    Point(){
    }
    bool operator<(const Point &other)const{
        if(x!=other.x){
            return xreturn y>other.y;
    }
};

Point ch[maxn];
vector pts[maxn<<1];

void update(int tl,int tr,int l,int r,Point pt){
    if(l == tl && r == tr){
        pts[getID(l,r)].push_back(pt);
        return;
    }
    int mid = (tl+tr)>>1;
    if(r <= mid){
        update(tl,mid,l,r,pt);
    }else{
        if(l > mid){
            update(mid+1,tr,l,r,pt);
        }else{
            update(tl,mid,l,mid,pt);
            update(mid+1,tr,mid+1,r,pt);
        }
    }
}

int sz; //ConvexHull's size

int n;

void ConvexHull(int id){
    sort(pts[id].begin(),pts[id].end());
    sz = 0;
    Point pre = Point(-INF,-INF);
    for(int i=0;i<(int)pts[id].size();i++){
        Point pt = pts[id][i]; 
        if(pt.x == pre.x){
            continue;
        }
        pre = pt;
        if(sz<2){
            ch[sz++] = pt;
        }else{
            while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >= 
                    (ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
                sz--;
            }
            ch[sz++] = pt;
        }
    }
}

inline ll calc(int ptid,int qid){
    return ch[ptid].y+ch[ptid].x*a[qid];
}

ll bs(int l,int r,int qid){
    int L = l;
    int R = r;
    ll res = -INF;
    while(l<=r){
        int mid = (l+r)>>1;
        ll mval = calc(mid,qid);
        res = max(res,mval);
        if(mid > L && calc(mid-1,qid) > mval){
            r = mid-1;
        }else if(mid < R && calc(mid+1,qid) > mval){
            l = mid+1;
        }else{
            break;
        }
    }
    return res;
} 

void cdq(int l,int r){
    int mid = (l+r)>>1;

    if(lif(l1,r);

    ConvexHull(getID(l,r));
    for(int i=l;i<=r;i++){
        if(t[i] == 3){
            ans[i] = max(ans[i],bs(0,sz-1,i));
        }
    }
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%d",&t[i]);
        if(t[i] == 1){
            scanf("%I64d%I64d",&a[i],&b[i]);
            r[i] = n;
        }else{
            scanf("%I64d",&a[i]);
            if(t[i] == 2){
                r[a[i]] = i-1;
            }
        }
        ans[i] = -INF;
    }

    for(int i=1;i<=n;i++){
        if(t[i] == 1){
            if(i+1<=r[i])update(1,n,i+1,r[i],Point(a[i],b[i]));
        }
    }

    cdq(1,n);

    for(int i=1;i<=n;i++){
        if(t[i] == 3){
            if(ans[i] == -INF){
                printf("EMPTY SET\n");
            }else{
                printf("%I64d\n",ans[i]);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(数据结构)