JZOJ 5067. 【GDOI2017第二轮模拟day2】有理有据题 (KD-tree+历史最值问题)
https://gmoj.net/senior/#main/show/5067
题解:
考虑\([l,r]∩[x,y] \ne ∅\)的充要条件是\(max(l,x)\le min(r,y)\)
即\(l \le y且 x \le r\)
那么每次相当于修改矩形内的点。
套上一个K-D tree,问题变成了:
- 区间加
- 区间赋值
- 询问单点历史最大值
这个可以直接lazytag搞定,通过思考一个操作序列需要保留什么东西即可实现。
Code:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 50005;
int n, m, Q;
struct P {
int x, y, i;
} a[N];
void Init() {
scanf("%d %d %d", &n, &m, &Q);
fo(i, 1, n) {
scanf("%d %d", &a[i].x, &a[i].y);
if(a[i].x > a[i].y) swap(a[i].x, a[i].y);
a[i].y = -a[i].y;
swap(a[i].x, a[i].y);
a[i].i = i;
}
}
struct nod {
bool bz;
int m1, m2, s;
nod() { bz = m1 = m2 = s = 0;}
};
void jia(nod &a, int v) {
if(!a.bz) {
a.s += v;
a.m1 = max(a.m1, a.s);
} else {
a.s += v;
a.m2 = max(a.m2, a.s);
}
}
void fz(nod &a) {
a.bz = 1;
a.s = 0;
}
void mer(nod &a, nod b) {
if(!a.bz) {
if(!b.bz) {
a.bz = 0;
a.m1 = max(a.m1, a.s + b.m1);
a.s += b.s;
} else {
a.bz = 1;
a.m1 = max(a.m1, a.s + b.m1);
a.m2 = b.m2;
a.s = b.s;
}
} else {
if(!b.bz) {
a.bz = 1;
a.m2 = max(a.m2, a.s + b.m1);
a.s += b.s;
} else {
a.bz = 1;
a.m2 = max(a.m2, max(a.s + b.m1, b.m2));
a.s = b.s;
}
}
}
#define i0 i + i
#define i1 i + i + 1
struct tree {
int mi[2], mx[2];
nod v;
} t[N * 4];
int rt = 1;
int o;
int cmp(P a, P b) {
return o ? a.y < b.y : a.x < b.x;
}
int ia[N];
#define db double
int ca(int x, int y) {
db s1 = 0, s2 = 0;
fo(i, x, y) {
s1 += a[i].x;
s2 += a[i].y;
}
s1 /= (y - x + 1);
s2 /= (y - x + 1);
db v1 = 0, v2 = 0;
#define sqr(x) ((x) * (x))
fo(i, x, y) {
v1 += sqr(a[i].x - s1);
v2 += sqr(a[i].y - s2);
}
return v1 > v2 ? 0 : 1;
}
void bt(int i, int x, int y) {
if(x == y) {
t[i].mi[0] = t[i].mx[0] = a[x].x;
t[i].mi[1] = t[i].mx[1] = a[x].y;
ia[a[x].i] = x;
return;
}
o = ca(x, y) ;
int m = x + y >> 1;
nth_element(a + x, a + m, a + y + 1, cmp);
bt(i0, x, m); bt(i1, m + 1, y);
fo(j, 0, 1) {
t[i].mi[j] = min(t[i0].mi[j], t[i1].mi[j]);
t[i].mx[j] = max(t[i0].mx[j], t[i1].mx[j]);
}
}
void down(int i) {
if(t[i].v.bz || t[i].v.m1 || t[i].v.s) {
mer(t[i0].v, t[i].v);
mer(t[i1].v, t[i].v);
t[i].v = nod();
}
}
int pl[2], pr[2];
void add(int i, int x, int y) {
if(t[i].mi[0] > pr[0] || t[i].mi[1] > pr[1]) {
fz(t[i].v);
return;
}
if(t[i].mx[0] <= pr[0] && t[i].mx[1] <= pr[1]) {
jia(t[i].v, 1);
return;
}
int m = x + y >> 1; down(i);
add(i0, x, m); add(i1, m + 1, y);
}
int pz, px;
void ft(int i, int x, int y) {
if(x == y) {
px = max(t[i].v.m1, t[i].v.m2);
return;
}
int m = x + y >> 1; down(i);
if(pz <= m) ft(i0, x, m); else ft(i1, m + 1, y);
}
char str[11];
int x, y;
void cz(int x, int y) {
if(x > y) swap(x, y);
x = -x;
pl[0] = pl[1] = -1e9;
pr[0] = x, pr[1] = y;
add(rt, 1, n);
}
int qry(int x) {
pz = ia[x]; px = 0;
ft(rt, 1, n);
}
void End() {
fo(i, 1, m) {
scanf("%d %d", &x, &y);
cz(x, y);
}
fo(i, 1, Q) {
scanf("%s", str + 1);
if(str[1] == 'A') {
scanf("%d %d", &x, &y);
cz(x, y);
}
if(str[1] == 'C') {
scanf("%d", &x);
pp("%d\n", qry(x));
}
if(str[1] == 'Q') {
int s = 0;
fo(j, 1, n) s ^= qry(j);
pp("%d\n", s);
}
}
}
int main() {
freopen("bomb.in", "r", stdin);
freopen("bomb.out", "w", stdout);
Init();
bt(rt, 1, n);
End();
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址