作者:手机用户2502922685 | 来源:互联网 | 2023-08-30 17:22
本文由编程笔记#小编为大家整理,主要介绍了bzoj4237: 稻草人 cdq分治 单调栈相关的知识,希望对你有一定的参考价值。
目录
题目链接
bzoj4237: 稻草人
题解
暴力统计是n^2的
考虑统计一段区间对另一端的贡献
对于y值cdq分治,降调一维
对于当前两个分治区间统计上面那部分对下面那部分的贡献
对当前两区间x排序后,对上部分维护单增单调栈,得到距离当前点最近的比她低的点p
对于下面的区间维护一个上凸壳 ,直接在凸壳上二分p统计答案
代码
#include
#include
#include
#include
#define gc getchar()
#define pc putchar
#define LL long long
inline int read() {
int x = 0,f = 1;
char c = gc;
while(c <&#39;0&#39; || c > &#39;9&#39;) c = gc;
while(c <= &#39;9&#39; && c >= &#39;0&#39;) x = x * 10 + c - &#39;0&#39;,c = gc;
return x * f;
}
void print(LL x) {
if(x <0) {
pc(&#39;-&#39;);
x = -x;
}
if(x >= 10) print(x / 10);
pc(x % 10 + &#39;0&#39;);
}
const int maxn = 200007;
struct Point {
int x,y;
} po[maxn];
int n;
bool cmpx(Point a,Point b) { return a.x bool cmpy(Point a,Point b) { return a.y int tp,tl;
int sk[maxn],sk2[maxn];
LL ans = 0;
void solve(int l = 1,int r = n) {
if(l == r) return ;
int mid = l + r >> 1;
std::sort(po + l,po + r + 1,cmpy);
std::sort(po + l,po + mid + 1,cmpx); //down
std::sort(po + mid + 1,po + r + 1,cmpx); //up
tp = tl = 0;
int p = l,L,R,to,miid,lim;
for(int i = mid + 1;i <= r;++ i) {
while(tp && po[sk[tp]].y >= po[i].y) tp --;
sk[++ tp] = i;
for(;p <= mid && po[p].x while(tl && po[sk2[tl]].y <= po[p].y) tl --;
sk2[++ tl] = p;
}
L = 1,R = tl;to = - 1;lim = po[sk[tp - 1]].x;
while(L <= R) {
miid = L + R >> 1;
if(po[sk2[miid]].x > lim) to = miid,R = miid - 1;
else L = miid + 1;
}
if(to != -1) ans += 1ll * tl - 1ll * to + 1;
}
solve(l,mid); solve(mid + 1,r);
}
int main() {
n = read();
for(int i = 1;i <= n;++ i) {
po[i].x = read(),po[i].y = read();
}
po[0].x = po[0].y = -1;
solve();
print(ans);
pc(&#39;
&#39;);
}