题解:P14426 [JOISC 2014] 稻草人 / Scarecrows
题意
平面上存在
思路
先对
先将点按照
再考虑第三个限制,对于左区间的点,可以用单调栈维护,当加入一个点时,弹出其左下角所有点,这些点一定是没有贡献的,然后按这个思路写了一个代码,发现样例都过不了,因为只考虑了左边点出现在矩形中的影响,而没有考虑右边的点,假设右区间存在点
那么限制就可以转化为找
复杂度
代码
注意要开 long long。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,ls[N];
long long ans=0;
struct node{
int x,y;
}a[N];
bool cmpx(node A,node B){
return A.x<B.x;
}
bool cmpy(node A,node B){
return A.y<B.y;
}
struct Tree{
int t[N];
#define lobit(x) (x&(-x))
void operator () (int x,int c){
for(;x<=n;x+=lobit(x)) t[x]+=c;
}
int operator [] (int x){
int ans=0;
for(;x;x-=lobit(x)) ans+=t[x];
return ans;
}
#undef lobit(x)
}T;
struct M{
int t[N];
#define lobit(x) (x&(-x))
void operator () (int x,int c){
for(;x<=n;x+=lobit(x)) if(c) t[x]=max(t[x],c); else t[x]=0;
}
int operator [] (int x){
int ans=0;
for(;x;x-=lobit(x)) ans=max(ans,t[x]);
return ans;
}
#undef lobit(x)
}F;
int stk[N];
void solve(int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
solve(l,mid);solve(mid+1,r);
sort(a+l,a+mid+1,cmpy);sort(a+mid+1,a+r+1,cmpy);
int i=mid+1,j=l,top=0;
for(;i<=r;i++){
for(;j<=mid && a[j].y<a[i].y;j++){
while(top && a[stk[top]].x<a[j].x) T(a[stk[top--]].y,-1);
stk[++top]=j;
T(a[j].y,1);
}
ans+=T[a[i].y]-T[F[a[i].x]];
F(a[i].x,a[i].y);
}
while(top) T(a[stk[top--]].y,-1);
for(int i=mid+1;i<=r;i++) F(a[i].x,0);
// cout<<l<<" "<<r<<" "<<ans<<"\n";
}
signed mian(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y,ls[i]=a[i].x;
sort(ls+1,ls+n+1);
for(int i=1;i<=n;i++) a[i].x=lower_bound(ls+1,ls+n+1,a[i].x)-ls;
for(int i=1;i<=n;i++) ls[i]=a[i].y;
sort(ls+1,ls+n+1);
for(int i=1;i<=n;i++) a[i].y=lower_bound(ls+1,ls+n+1,a[i].y)-ls;
sort(a+1,a+n+1,cmpx);
solve(1,n);
cout<<ans;
return 0;
}