CF678F Lena and Queries

https://www.luogu.com.cn/problem/CF678F

首先一眼线段树分治

然后线段树上每个节点建一个凸包,在上面三分即可

code:


#include<bits/stdc++.h>
#define ll long long
#define N 300050
using namespace std;
const ll inf = 2e18;
struct P {
    ll x, y;
    P operator + (const P o) {return (P){x + o.x, y + o.y}; }
    P operator - (const P o) {return (P){x - o.x, y - o.y}; }
    ll operator * (const P o) {return x * o.y - y * o.x; }
    bool operator < (const P o) const {return x == o.x? y < o.y : x < o.x; }
} a[N], sta[N];

ll cross(P a, P b, P c) {
    return (b - a) * (c - a);
}
ll calc(P o, ll k) {
    //printf("%lld %lld  %lld\n", o.x, o.y, k);
    return k * o.x + o.y;
}
struct TB {
    vector<P> v;
    void push(P x) {v.push_back(x);}
    void px() {
        sort(v.begin(), v.end());
        //printf("%d\n", v.size());
        //for(auto x : v) printf("(%lld %lld) ", x.x, x.y); printf("\n");
        int top = 0; 
        for(auto x : v) {
            while(top > 1 && cross(sta[top - 1], sta[top], x) >= 0) top --;
            sta[++ top] = x;
        }
        v.clear();
        for(int i = 1; i <= top; i ++) v.push_back(sta[i]);
        //printf("** %d\n", top);
    }
    ll query(ll k) {
        if(!v.size()) return - inf;
        int l = 0, r = v.size() - 1;
        while(l + 1 < r) {
            int mid = (l + r) >> 1;
            if(calc(v[mid], k) < calc(v[mid + 1], k)) l = mid;
            else r = mid;
        }
    //    printf("%lld   (%lld %lld)  %lld  \n", k, v[0].x, v[0].y, calc(v[0], k));
        return max(calc(v[l], k), calc(v[r], k));
    }
} V[N << 3];

#define ls (rt << 1)
#define rs (rt << 1 | 1)
void insert(int rt, int l, int r, int L, int R, P o) {
    if(L <= l && r <= R) {
    //    printf("** %d %d  %d\n", l, r, o.x);
        V[rt].push(o);
        return ;
    }
    int mid = (l + r) >> 1;
    if(L <= mid) insert(ls, l, mid, L, R, o);
    if(R > mid) insert(rs, mid + 1, r, L, R, o);
}
void build(int rt, int l, int r) {
    V[rt].px();
    if(l == r) return ;
    int mid = (l + r) >> 1;
    build(ls, l, mid), build(rs, mid + 1, r);
}
ll query(int rt, int l, int r, int x, ll k) {
    ll ret = V[rt].query(k);
    //printf("   %d %d %d %d  %lld  %d\n", l, r, L, R, k, (int)V[rt].v.size());
    if(l == r) return ret;
    int mid = (l + r) >> 1;
    if(x <= mid) ret = max(ret, query(ls, l, mid, x, k));
    else ret = max(ret, query(rs, mid + 1, r, x, k));
    return ret;
}
int n, o[N], R[N], k[N];
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) {
        int x;
        scanf("%d", &o[i]);
        if(o[i] == 1) {
            scanf("%lld%lld", &a[i].x, &a[i].y);
            R[i] = n;
        } 
        if(o[i] == 2) {
            scanf("%d", &x);
            R[x] = i;
        }
        if(o[i] == 3) {
            scanf("%d", &k[i]);
        }
    }

    for(int i = 1; i <= n; i ++) if(R[i]) {
        insert(1, 1, n, i, R[i], a[i]);
    }
    build(1, 1, n);

    for(int i = 1; i <= n; i ++) if(o[i] == 3) {
        ll ret = query(1, 1, n, i, k[i]);
        if(ret == -inf) printf("EMPTY SET\n");
        else printf("%lld\n", ret);
    }
    return 0;
}
上一篇:Codeforces 1633 C. Kill the Monster —— 暴力


下一篇:GraphQL:Interface和子类怎么查?