洛谷传送门
BZOJ传送门
题目描述
要求在平面直角坐标系下维护两个操作:
- 在平面上加入一条线段。记第 i i i 条被插入的线段的标号为 i i i
- 给定一个数 k k k,询问与直线 x = k x = k x=k 相交的线段中,交点最靠上的线段的编号。
输入输出格式
输入格式:
第一行一个整数 n n n,表示共 n n n 个操作
接下来 n n n 行,每行第一个数为 0 0 0 或 1 1 1
若该数为 0 0 0,则后面跟着一个正整数 k k k,表示询问与直线 x = ( ( k + l a s t a n s – 1 ) % 39989 + 1 ) x = ((k + lastans – 1)\%39989+1) x=((k+lastans–1)%39989+1)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中%表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段 y 坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号
若该数为 1 1 1,则后面跟着四个正整数 x 0 , y 0 , x 1 , y 1 x_0, y_0, x_1, y_1 x0,y0,x1,y1,表示插入一条两个端点为 ( ( x 0 + l a s t a n s − 1 ) ((x_0+lastans-1)%39989+1,(y_0+lastans-1)%10^9+1) ((x0+lastans−1)和 ( ( x 1 + l a s t a n s − 1 ) ((x_1+lastans-1)%39989+1,(y_1+lastans-1)%10^9+1) ((x1+lastans−1) 的线段
其中 l a s t a n s lastans lastans 为上一次询问的答案。初始时 l a s t a n s = 0 lastans=0 lastans=0
输出格式:
对于每个 0 0 0 操作,输出一行,包含一个正整数,表示交点最靠上的线段的编 号。若不存在与直线相交的线段,答案为 0 0 0
输入输出样例
输入样例#1:
6
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5
输出样例#1:
2
0
3
说明
对于
30
%
30\%
30%的数据,
n
≤
1000
n ≤ 1000
n≤1000
对于
100
%
100\%
100%的数据,
1
≤
n
≤
1
0
5
,
1
≤
k
,
x
0
,
x
1
≤
39989
,
1
≤
y
0
≤
y
1
≤
1
0
9
1 ≤ n ≤ 10^5, 1 ≤ k, x_0, x_1 ≤ 39989, 1 ≤ y_0 ≤ y_1 ≤ 10^9
1≤n≤105,1≤k,x0,x1≤39989,1≤y0≤y1≤109
解题分析
李超线段树板题。
对于一个区间 [ l , r ] [l,r] [l,r], 我们维护在 m i d mid mid位置最高的那条线段。
更新时如果在 [ l , r ] [l,r] [l,r]新加入的线段比原来的线段更劣或更优, 就直接覆盖或return。
否则留下中间更高的那个线段, 然后将更低的那条较高的一端下放更新。
这样每条线段会对应 l o g ( N ) log(N) log(N)个区间, 下放的复杂度是 l o g ( N ) log(N) log(N), 所以总复杂度 O ( n l o g 2 ( n ) ) O(nlog^2(n)) O(nlog2(n))。
注意有平行于 y y y轴的线段, 这种情况直接将函数表达式改成最高的那个点。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define db double
#define ls (now << 1)
#define rs (now << 1 | 1)
#define MX 100500
#define MOD 1000000000
#define EPS 1e-8
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
template <class T> IN T max(T a, T b) {return a > b ? a : b;}
template <class T> IN T min(T a, T b) {return a < b ? a : b;}
template <class T> IN T abs(T a) {return a > 0 ? a : -a;}
int n, lastans = -1, tot;
struct Node {int id; bool use;} tree[MX << 1];
struct Line {db k, b;} line[MX];
IN db f(R int id, R int x) {return line[id].k * x + line[id].b;}
IN bool better(R int x, R int y, R int pos)
{
db fx = f(x, pos), fy = f(y, pos);
if (abs(fx - fy) < EPS) return x < y;
else return fx > fy;
}
void insert(R int now, R int lef, R int rig, R int lb, R int rb, R int id)
{
if (rb < lef || lb > rig) return;
int mid = lef + rig >> 1;
if (lb <= lef && rb >= rig)
{
if (better(id, tree[now].id, lef) && better(id, tree[now].id, rig))
return tree[now].id = id, void();
if (better(tree[now].id, id, lef) && better(tree[now].id, id, rig))
return;
if (better(id, tree[now].id, mid)) std::swap(tree[now].id, id);
if (better(id, tree[now].id, lef)) insert(ls, lef, mid, lef, rig, id);
else insert(rs, mid + 1, rig, lef, rig, id);
return;
}
insert(ls, lef, mid, lb, rb, id);
insert(rs, mid + 1, rig, lb, rb, id);
}
int query(R int now, R int lef, R int rig, R int tar)
{
if (lef == rig) return tree[now].id;
int mid = lef + rig >> 1, ret;
if (tar <= mid)
{
ret = query(ls, lef, mid, tar);
return better(ret, tree[now].id, tar) ? ret : tree[now].id;
}
else
{
ret = query(rs, mid + 1, rig, tar);
return better(ret, tree[now].id, tar) ? ret : tree[now].id;
}
}
int main(void)
{
in(n);
int lx, ly, rx, ry, typ, pos;
for (R int i = 1; i <= n; ++i)
{
in(typ);
if (typ & 1)
{
in(lx), in(ly), in(rx), in(ry);
lx = (lx + lastans + 39989) % 39989 + 1;
ly = (ly + lastans + MOD) % MOD + 1;
rx = (rx + lastans + 39989) % 39989 + 1;
ry = (ry + lastans + MOD) % MOD + 1;
++tot;
if (lx > rx) std::swap(lx, rx), std::swap(ly, ry);
if (lx == rx) line[tot] = {0, max(ly, ry)};
else line[tot].k = 1.0 * (ry - ly) / (rx - lx), line[tot].b = ly - lx * line[tot].k;
insert(1, 1, 40000, lx, rx, tot);
}
else
{
in(pos);
pos = (pos + lastans + 39989) % 39989 + 1;
lastans = query(1, 1, 40000, pos);
printf("%d\n", lastans);
lastans--;
}
}
}