某岛

… : "…アッカリ~ン . .. . " .. .
September 12, 2021

BZOJ 3165. [Heoi2013]Segment

记一下模板的写法。。。

做法一:李超树
https://github.com/lychees/ACM-Training/tree/master/Archive/BZOJ/3165.%20%5BHeoi2013%5DSegment

做法二:线段树套平衡树

因为李超树的大流行,树套树反而没人再去写了。。。

const int N = int(1e5) + 9;

#define ll double
struct Line {
	mutable ll k, b, p; int id;
	Line (ll k = 0, ll b = 0, int id = 0):k(k),b(b),id(id) {
	    p = 0;
	}
	ll y(ll x) const {return k*x + b;}
	bool operator<(const Line& o) const { return k < o.k; }
	bool operator<(ll x) const { return p < x; }
};

struct LineContainer : multiset<Line,less<>> {
	const ll inf = 1/.0;
	ll div(ll a, ll b) {
		return a / b;
    }
	bool isect(iterator x, iterator y) {
		if (y == end()) return x->p = inf, 0;
		if (x->k == y->k) x->p = x->b > y->b ? inf : -inf;
		else x->p = div(y->b - x->b, x->k - y->k);
		return x->p >= y->p;
	}
	void add(ll k, ll b, int i) {
		add(Line(k,b,i));
	}
	void add(Line t) {
		auto z = insert(t), y = z++, x = y;
		while (isect(y, z)) z = erase(z);
		if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
		while ((y = x) != begin() && (--x)->p >= y->p)
			isect(x, erase(y));
	}

	pair<ll, int> query(ll x) {
		assert(!empty());
		auto& l = *lower_bound(x);
		return {l.y(x), l.id};
	}
} H;
map<int, pair<ll,int> > M;


namespace Segtree {
    const int NN = 4 * N;
    LineContainer T[NN];
#define lx (x<<1)
#define rx (lx|1)
#define ml ((l+r)>>1)
#define mr (ml+1)
#define lc lx, l, ml
#define rc rx, mr, r
#define rt 1,1,39989
    void Insert(int x, int l, int r, int a, int b, Line L) {
        if (b < l || r < a) return;
        if (a <= l && r <= b) {
            T[x].add(L);
        } else {
            Insert(lc, a, b, L);
            Insert(rc, a, b, L);
        }
    }
    void Query(int x, int l, int r, int p, vector<LineContainer*>& L) {
        if (p < l || r < p) return;
        if (l <= p && p <= r) {
            if (!T[x].empty()) L.PB(&T[x]);
        }
        if (l != r) {
            Query(lc, p, L);
            Query(rc, p, L);
        }
    }
}

vector<LineContainer*> L;

int main(){

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif

    int id = 0; Rush {
        LL x0, y0, x1, y1;
        if (RD()) {
            RD(x0, y0, x1, y1);
            x0 = (x0 + last_ans - 1) % 39989 + 1;
            x1 = (x1 + last_ans - 1) % 39989 + 1;
            y0 = (y0 + last_ans - 1) % int(1e9) + 1;
            y1 = (y1 + last_ans - 1) % int(1e9) + 1;
            if (x0 > x1) {
                swap(x0, x1);
                swap(y0, y1);
            }
            if (x0 == x1) {
                auto t = pair<ll, int>(max(y0, y1), ++id);
                if (CTN(M, x0))  {
                    M[x0] = t;
                } else {
                    checkMax(M[x0], t);
                }
            } else {
                DB k = (DB)(y1-y0)/(x1-x0);
                DB b = y0 - k*x0;
                Segtree::Insert(rt, x0, x1, Line(k, b, ++id));
            }
        } else {
            RD(x0);
            x0 = (x0 + last_ans - 1) % 39989 + 1;
            pair<ll, int> z = {-OO, 0}; L.clear(); Segtree::Query(rt, x0, L);
            for (auto& l: L) checkMax(z, l->query(x0));
            if (CTN(M, x0)) checkMax(z, M[x0]);
            OT(z.se);
        }
    }
}