BZOJ 3533 向量集(凸包 + 二分 + 线段树)

题目:传送门

题意

 1 < =N < =4*10^5

思路

思路参考 ->

代码参考->

#include <bits/stdc++.h>
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define pb push_back
using namespace std;

typedef long long LL;
const LL inf = 0x3f3f3f3f3f3f3f3fLL;
const int N = 400050;

struct Point {
    LL x, y;
    Point() { }
    Point(LL x = 0, LL y = 0) : x(x), y(y) { }
    LL operator * (const Point&a)const{return x*a.x+y*a.y;}
    LL operator ^ (const Point&a)const{return y*a.x-x*a.y;}
    Point operator + (const Point&a)const{return Point(x+a.x,y+a.y);}
    Point operator - (const Point&a)const{return Point(x-a.x,y-a.y);}
    bool operator < (const Point&a)const{return x==a.x?y<a.y:x<a.x;}
};

LL ans;
char s[5], ch[5];
int n, tot, x, y, l, r;
vector < Point > tmp[N << 2], up[N << 2], dw[N << 2];

void add(int rt, int l, int r, LL x, LL y, int pos) {
    tmp[rt].pb(Point(x, y));
    if(pos == r) {
        sort(tmp[rt].begin(), tmp[rt].end());
        for(int i = 0; i < tmp[rt].size(); i++) {
            while(up[rt].size() > 1 && ((up[rt][up[rt].size() - 1] - up[rt][up[rt].size() - 2]) ^ (tmp[rt][i] - up[rt][up[rt].size() - 1])) <= 0)
                up[rt].pop_back();
            up[rt].pb(tmp[rt][i]);

            while(dw[rt].size() > 1 && ((dw[rt][dw[rt].size() - 1] - dw[rt][dw[rt].size() - 2]) ^ (tmp[rt][i] - dw[rt][dw[rt].size() - 1])) >= 0)
                dw[rt].pop_back();
            dw[rt].pb(tmp[rt][i]);
        }
    }

    if(l == r) return ;

    int mid = (l + r) >> 1;
    if(pos <= mid) add(rt << 1, l, mid, x, y, pos);
    else add(rt << 1 | 1, mid + 1, r, x, y, pos);
}

void query(int rt, int l, int r, int L, int R, Point t) {
    if(L <= l && r <= R) {
        if(t.y >= 0) {
            int nowl = 1, nowr = up[rt].size() - 1, pos = 0;
            while(nowl <= nowr) {
                int mid = (nowl + nowr) >> 1;
                if(t * up[rt][mid] > t * up[rt][mid - 1]) {
                    pos = mid; nowl = mid + 1;
                }
                else nowr = mid - 1;
            }
            ans = max(ans, t * up[rt][pos]);
        }
        else {
            int nowl = 1, nowr = dw[rt].size() - 1, pos = 0;
            while(nowl <= nowr) {
                int mid = (nowl + nowr) >> 1;
                if(t * dw[rt][mid] > t * dw[rt][mid - 1]) {
                    pos = mid; nowl = mid + 1;
                }
                else nowr = mid - 1;
            }
            ans = max(ans, t * dw[rt][pos]);
        }
        return ;
    }
    int mid = (l + r) >> 1;
    if(L <= mid) query(rt << 1, l, mid, L, R, t);
    if(R > mid) query(rt << 1 | 1, mid + 1, r, L, R, t);
}


int main() {
    scanf("%d %s", &n, s);

    for(int i = 1; i <= n; i++) {
        scanf("%s %d %d", ch, &x, &y);
        if(s[0] != 'E') x ^= ans, y ^= ans;
        if(ch[0] == 'A') {
            tot++;
            add(1, 1, n, x, y, tot);
        }
        else {
            scanf("%d %d", &l, &r);
            if(s[0] != 'E') l ^= ans, r ^= ans;
            ans = -inf;
            query(1, 1, n, l, r, Point(x, y));
            printf("%lld
", ans);
            ans &= 0x7fffffff;
        }
    }
    return 0;
}
一步一步,永不停息
原文地址:https://www.cnblogs.com/Willems/p/12570862.html