[HEOI2013]Segment【李超线段树】

题目链接


  有N次操作,强制在线,每次要么查询x == x_0时候的与已有线段的最大交点值的对应线段序号,要么就是插入一个线段(x_{0}, y_{0})\rightarrow (x_{1}, y_{1})

  于是,就是一个很明显的一个李超线段树了,用永久化标记来进行操作,当插入对应区间的时候,利用它和已有的覆盖线段来进行比较,我们可以知道它们的关系。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 4e4 + 10;
int N;
const int mod = 39989, MOD = 1e9;
pair<double, double> line[100005];
int t[maxN << 2] = {0};
const int UL = 0, UR = 4e4;
double H[maxN] = {0};
int hid[maxN] = {0};
inline void update(int rt, int l, int r, int xl, int xr, int v)
{
    int mid = HalF;
    int u = t[rt];
    if(xl <= l && xr >= r)
    {
        if(u)
        {
            double old = line[u].first * mid + line[u].second;
            double now = line[v].first * mid + line[v].second;
            if(line[v].first > line[u].first)
            {
                if(old < now)
                {
                    t[rt] = v;
                    if(l ^ r) update(Lson, xl, xr, u);
                }
                else
                {
                    if(l ^ r) update(Rson, xl, xr, v);
                }
            }
            else if(line[v].first < line[u].first)
            {
                if(old >= now)
                {
                    if(l ^ r) update(Lson, xl, xr, v);
                }
                else
                {
                    t[rt] = v;
                    if(l ^ r) update(Rson, xl, xr, u);
                }
            }
            else
            {
                if(line[u].second < line[v].first)
                {
                    t[rt] = v;
                }
            }
        }
        else
        {
            t[rt] = v;
        }
        return;
    }
    if(l == r) return;
    if(xr <= mid) update(Lson, xl, xr, v);
    else if(xl > mid) update(Rson, xl, xr, v);
    else { update(Lson, xl, xr, v); update(Rson, xl, xr, v); }
}
double ans = 0;
int ans_id = 0;
void query(int rt, int l, int r, double qx)
{
    int u = t[rt];
    if(u)
    {
        double y = line[u].first * qx + line[u].second;
        if(y > ans)
        {
            ans = y;
            ans_id = u;
        }
        else if(y == ans)
        {
            ans_id = min(ans_id, u);
        }
    }
    if(l == r) return;
    int mid = HalF;
    if(qx <= mid) query(Lson, qx);
    else query(Rson, qx);
}
inline void ID(int &x) { x = (x + ans_id - 1) % mod + 1; }
inline void CD(int &y) { y = (y + ans_id - 1) % MOD + 1; }
int main()
{
    scanf("%d", &N);
    int cnt = 0;
    for(int i=1, op, x[3], y[3]; i<=N; i++)
    {
        scanf("%d", &op);
        if(!op)
        {
            scanf("%d", &x[0]);
            ID(x[0]);
            ans = -1; ans_id = 0;
            query(1, UL, UR, x[0]);
            if(hid[x[0]] && ans < H[x[0]])
            {
                ans = H[x[0]];
                ans_id = hid[x[0]];
            }
            printf("%d\n", ans_id);
        }
        else
        {
            scanf("%d%d%d%d", &x[0], &y[0], &x[1], &y[1]);
            ID(x[0]); CD(y[0]); ID(x[1]); CD(y[1]);
            if(x[0] == x[1])
            {
                if(y[0] > y[1]) swap(y[0], y[1]);
                if(H[x[0]] < y[1])
                {
                    H[x[0]] = y[1];
                    hid[x[0]] = ++cnt;
                    continue;
                }
            }
            if(x[0] > x[1])
            {
                swap(x[0], x[1]);
                swap(y[0], y[1]);
            }
            double det_y = y[1] - y[0], det_x = x[1] - x[0];
            double k = det_y / det_x;
            double b = 1. * y[0] - k * x[0];
            line[++cnt] = make_pair(k, b);
            update(1, UL, UR, x[0], x[1], cnt);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/107809670