题解:P14426 [JOISC 2014] 稻草人 / Scarecrows
CatFromMars · · 题解
千古神犇大 Toorean 给我看的题目。因为我是感冒期间口胡的,然后好像看错图了,接下来我们认为枚举的点对是左上角和右下角的点对,而并不是题目中左下角和右上角的点对。
注意到产生贡献的点对形式很怪,于是绝大部分情况下可以直接考虑分治。考虑一下按照
若
为了刻画中间没有任何点,提前与处理小于等于
有用的
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5;
namespace bit {
int sum[N + 10], lim;
int lowbit(int x) {
return x & (-x);
}
void upd(int x, int y) {
x++;
while(x <= lim + 1) sum[x] += y, x += lowbit(x);
}
int qry(int x) {
x++; int rest = 0;
while(x)
rest += sum[x], x -= lowbit(x);
return rest;
}
}
struct node {
int x, y;
} D[N + 10], P[N + 10];
bool cmp(node &a, node &b) {
return a.x < b.x;
}
bool cmpp(node &a, node &b) {
return a.y < b.y;
}
int n, cpx[N + 10], cpy[N + 10];
ll ans = 0;
int ty[N + 10], sy[N + 10];
void solve(int l, int r) {
if(l >= r) return ;
int mid = (l + r) >> 1;
solve(l, mid);
solve(mid + 1, r);
set <int> st;
for(int i = mid; i >= l; i--) {
if(st.empty()) ty[i] = 0;
else {
set <int>::iterator it = st.upper_bound(D[i].y);
if(it == st.begin()) ty[i] = 0;
else {
it--;
ty[i] = (*it);
}
}
st.insert(D[i].y);
P[i] = (node){ty[i], D[i].y};
}
st.clear();
for(int i = mid + 1; i <= r; i++) {
if(st.empty()) sy[i] = n + 1;
else {
set <int>::iterator it = st.upper_bound(D[i].y);
if(it == st.end()) sy[i] = n + 1;
else sy[i] = (*it);
}
st.insert(D[i].y);
P[i] = (node){D[i].y, sy[i]};
}
for(int i = mid + 1; i <= r; i++) {
bit::upd(D[i].y, 1);
bit::upd(sy[i], -1);
}
for(int i = l; i <= mid; i++)
ans += (bit::qry(D[i].y));
for(int i = mid + 1; i <= r; i++)
bit::upd(D[i].y, -1),
bit::upd(sy[i], 1);
sort(P + mid + 1, P + r + 1, cmp);
sort(P + l, P + mid + 1, cmp);
int j = mid + 1;
for(int i = l; i <= mid; i++) {
while(j <= r && P[j].x <= P[i].x)
bit::upd(P[j].y, 1), j++;
ans -= (bit::qry(bit::lim) - bit::qry(P[i].y));
}
for(int i = mid + 1; i < j; i++) bit::upd(P[i].y, -1);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
bit::lim = n + 5;
for(int i = 1; i <= n; i++)
cin >> D[i].x >> D[i].y, D[i].y = 1000000000 - D[i].y,
cpx[i] = D[i].x, cpy[i] = D[i].y;
int len;
sort(cpx + 1, cpx + n + 1);
len = unique(cpx + 1, cpx + n + 1) - cpx - 1;
for(int i = 1; i <= n; i++) D[i].x = lower_bound(cpx + 1, cpx + len + 1, D[i].x) - cpx;
sort(cpy + 1, cpy + n + 1);
len = unique(cpy + 1, cpy + n + 1) - cpy - 1;
for(int i = 1; i <= n; i++) D[i].y = lower_bound(cpy + 1, cpy + len + 1, D[i].y) - cpy;
sort(D + 1, D + n + 1, cmp);
solve(1, n);
cout << ans << '\n';
}