ln001 @ 2024-08-11 17:49:27
AC代码:
// Problem: P4097 【模板】李超线段树 / [HEOI2013] Segment
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4097
// Time Limit: 1000 ms
// Start Time:2024-08-11 09:52:44
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#ifndef LOCAL
#define csf std::cerr.setstate(std::ios_base::failbit)
#define db(x)
#else
#define db(x) cerr << __FUNCTION__ << " L" << __LINE__ << " " << #x " = " << (x) << endl
#define csf
#endif
using ll = long long;
#define double long double //add
#define f(x, y, z) for (ll x = (y); x <= (z); x++)
inline ll read();
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3f, N = 1e5 + 10, M = 4e4 + 10, Py = 1e9;
pair<double, double /*change -> ll to double*/> getf(ll xa, ll ya, ll xb, ll yb)
{
if (xa == xb)
return make_pair(0, max(ya, yb));
double k = (ya - yb);
k /= (xa - xb);
double b = ya - k * xa; // change
return make_pair(k, b);
}
struct edge
{
ll lx = INF, rx = -INF;
double k, b = -INF; //change
void init(ll xa, ll ya, ll xb, ll yb)
{
auto res = getf(xa, ya, xb, yb);
k = res.first;
b = res.second;
lx = min(xa, xb);
rx = max(xa, xb);
}
} e[N]; //线段
ll cnt = 0;
double get_y(ll x, ll id)
{
return e[id].k * x + e[id].b;
}
ll get_max(ll x, ll id1, ll id2)
{
double ya = get_y(x, id1); //change -> ll to double
double yb = get_y(x, id2);
if (ya == yb)
return min(id1, id2);
if (ya > yb)
return id1;
return id2;
}
bool has_intrsion(ll lx, ll rx, ll id1, ll id2)
{ //判断是否有交点
if (id1 == 0 || id2 == 0)
return 1;
if (get_y(lx, id1) == get_y(lx, id2))
return 1; //add
if (get_y(lx, id1) < get_y(lx, id2))
swap(id1, id2);
if (get_y(rx, id1) <= get_y(rx, id2))
return 1;
return 0;
}
bool intrsion_pos(ll lx, ll rx, ll id1, ll id2)
{ //如果交点在左侧返回0,在右侧返回1。在中间时返回0
ll mid = (lx + rx) / 2;
return has_intrsion(mid, rx, id1, id2); //change?
}
ll stick[M]; //竖直线段
ll n;
namespace lc_tree
{
#define ls(s) (s << 1)
#define rs(s) (s << 1 | 1)
struct node
{
ll l = INF, r = -INF; //区间范围
ll e; //线段标号(del -> 赋初值(默认为0))
} t[4 * M];
void build(ll p = 1, ll l = 1, ll r = 39989)
{
t[p].l = l;
t[p].r = r;
if (l == r)
return;
ll mid = (l + r) >> 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
}
void sent(ll id, ll p = 1)
{
if (e[id].lx > t[p].r || e[id].rx < t[p].l)
return;
else if (e[id].lx > t[p].l || e[id].rx < t[p].r)
{
if (t[p].l != t[p].r)
{
sent(id, ls(p));
sent(id, rs(p));
}
return;
}
ll oldd = t[p].e, neww = id, mid = (t[p].l + t[p].r) / 2;
if (get_max(mid, t[p].e, id) == id)
{ //替换当前区间
t[p].e = id;
swap(oldd, neww);
}
if (t[p].l != t[p].r && has_intrsion(t[p].l, t[p].r, oldd, neww))
{
if (get_y(mid, oldd) == get_y(mid, neww)) //add
{ //如果交点在中间
if (get_y(t[p].l, oldd) < get_y(t[p].l, neww)) //左侧更优
sent(neww, ls(p));
else
sent(neww, rs(p));
}
else
{
if (!intrsion_pos(t[p].l, t[p].r, oldd, neww)) //add
sent(neww, ls(p));
else
sent(neww, rs(p));
}
}
return;
}
ll check(ll x, ll p = 1)
{
ll res = 0;
if (t[p].l > x || t[p].r < x)
return 0;
res = get_max(x, res, t[p].e);
if (t[p].l != t[p].r)
{
res = get_max(x, res, check(x, ls(p)));
res = get_max(x, res, check(x, rs(p)));
}
return res;
}
#undef ls
#undef rs
} // namespace lc_tree
signed main()
{
csf;
cin >> n;
lc_tree::build();
ll lastans = 0;
f(i, 1, n)
{
ll op;
cin >> op;
if (op == 0)
{
ll k;
cin >> k;
ll ques = (k + lastans - 1) % 39989 + 1;
lastans = get_max(ques, stick[ques], lc_tree::check(ques)); //默认为0
cout << lastans << endl;
}
else
{
ll xa, ya, xb, yb;
cin >> xa >> ya >> xb >> yb;
xa = (xa + lastans - 1) % 39989 + 1;
xb = (xb + lastans - 1) % 39989 + 1;
ya = (ya + lastans - 1) % Py + 1;
yb = (yb + lastans - 1) % Py + 1;
e[++cnt].init(xa, ya, xb, yb);
if (xa == xb)
{
stick[xa] = get_max(xa, stick[xa], cnt);
}
else
{
lc_tree::sent(cnt);
}
}
}
return 0;
}
但是把intrsion_pos
函数第二行的return has_intrsion(mid, rx, id1, id2);
改成return has_intrsion(mid + 1, rx, id1, id2);
就WA了。
by ln001 @ 2024-08-11 17:52:34
重新补一个好看一点的AC代码
// Problem: P4097 【模板】李超线段树 / [HEOI2013] Segment
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4097
// Time Limit: 1000 ms
// Start Time:2024-08-11 09:52:44
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#ifndef LOCAL
#define csf std::cerr.setstate(std::ios_base::failbit)
#define db(x)
#else
#define db(x) cerr << __FUNCTION__ << " L" << __LINE__ << " " << #x " = " << (x) << endl
#define csf
#endif
using ll = long long;
#define double long double //add
#define f(x, y, z) for (ll x = (y); x <= (z); x++)
inline ll read();
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3f, N = 1e5 + 10, M = 4e4 + 10, Py = 1e9;
pair<double, double> getf(ll xa, ll ya, ll xb, ll yb) //由两点式转换为一般式
{
if (xa == xb)
return make_pair(0, max(ya, yb));
double k = (ya - yb);
k /= (xa - xb);
double b = ya - k * xa;
return make_pair(k, b);
}
struct edge
{
ll lx = INF, rx = -INF;
double k, b = -INF;
void init(ll xa, ll ya, ll xb, ll yb)
{
auto res = getf(xa, ya, xb, yb);
k = res.first;
b = res.second;
lx = min(xa, xb);
rx = max(xa, xb);
}
} e[N]; //线段
ll cnt = 0;
double get_y(ll x, ll id)
{
return e[id].k * x + e[id].b;
}
ll get_max(ll x, ll id1, ll id2)
{
double ya = get_y(x, id1);
double yb = get_y(x, id2);
if (ya == yb)
return min(id1, id2);
if (ya > yb)
return id1;
return id2;
}
bool has_intrsion(ll lx, ll rx, ll id1, ll id2)
{ //判断是否有交点
if (id1 == 0 || id2 == 0)
return 1;
if (get_y(lx, id1) == get_y(lx, id2))
return 1;
if (get_y(lx, id1) < get_y(lx, id2))
swap(id1, id2);
if (get_y(rx, id1) <= get_y(rx, id2))
return 1;
return 0;
}
bool intrsion_pos(ll lx, ll rx, ll id1, ll id2)
{ //如果交点在左侧返回0,在右侧返回1。在中间时返回0
ll mid = (lx + rx) / 2;
return has_intrsion(mid, rx, id1, id2);
}
ll stick[M]; //竖直线段
ll n;
namespace lc_tree
{
#define ls(s) (s << 1)
#define rs(s) (s << 1 | 1)
struct node
{
ll l = INF, r = -INF; //区间范围
ll e; //线段标号(del -> 赋初值(默认为0))
} t[4 * M];
void build(ll p = 1, ll l = 1, ll r = 39989)
{
t[p].l = l;
t[p].r = r;
if (l == r)
return;
ll mid = (l + r) >> 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
}
void sent(ll id, ll p = 1)
{
if (e[id].lx > t[p].r || e[id].rx < t[p].l)
return;
else if (e[id].lx > t[p].l || e[id].rx < t[p].r)
{
if (t[p].l != t[p].r)
{
sent(id, ls(p));
sent(id, rs(p));
}
return;
}
ll oldd = t[p].e, neww = id, mid = (t[p].l + t[p].r) / 2;
if (get_max(mid, t[p].e, id) == id)
{ //替换当前区间
t[p].e = id;
swap(oldd, neww);
}
if (t[p].l != t[p].r && has_intrsion(t[p].l, t[p].r, oldd, neww))
{
if (get_y(mid, oldd) == get_y(mid, neww)) //add
{ //如果交点在中间
if (get_y(t[p].l, oldd) < get_y(t[p].l, neww)) //左侧更优
sent(neww, ls(p));
else
sent(neww, rs(p));
}
else
{
if (!intrsion_pos(t[p].l, t[p].r, oldd, neww))
sent(neww, ls(p));
else
sent(neww, rs(p));
}
}
return;
}
ll check(ll x, ll p = 1)
{
ll res = 0;
if (t[p].l > x || t[p].r < x)
return 0;
res = get_max(x, res, t[p].e);
if (t[p].l != t[p].r)
{
res = get_max(x, res, check(x, ls(p)));
res = get_max(x, res, check(x, rs(p)));
}
return res;
}
#undef ls
#undef rs
} // namespace lc_tree
signed main()
{
csf;
cin >> n;
lc_tree::build();
ll lastans = 0;
f(i, 1, n)
{
ll op;
cin >> op;
if (op == 0)
{
ll k;
cin >> k;
ll ques = (k + lastans - 1) % 39989 + 1;
lastans = get_max(ques, stick[ques], lc_tree::check(ques));
cout << lastans << endl;
}
else
{
ll xa, ya, xb, yb;
cin >> xa >> ya >> xb >> yb;
xa = (xa + lastans - 1) % 39989 + 1;
xb = (xb + lastans - 1) % 39989 + 1;
ya = (ya + lastans - 1) % Py + 1;
yb = (yb + lastans - 1) % Py + 1;
e[++cnt].init(xa, ya, xb, yb);
if (xa == xb)
{
stick[xa] = get_max(xa, stick[xa], cnt);
}
else
{
lc_tree::sent(cnt);
}
}
}
return 0;
}