bzoj 1790: [Ahoi2008]Rectangle 矩形藏宝地

我的这种做法MLE一个点,cheat过去了。
把所有点按照x1排序,依次在线段树节点的x2位置加入区间[y1,y2]
查询时,查询线段树区间[x2,n]是否存在一个区间包含[y1,y2],在它之前加入的点的x1<这个点的x1,用线段树保证x2<那个x2
查询是否存在一个区间包含这个区间:
把这些区间去除被别的区间包含的区间,剩下的按照左端点排序,二分找到最大的y1<这个点的y1,然后看这个区间是否包含查询的区间。
显然,如果这个区间不包含查询的区间,那么其他区间也不可能,
维护互不包含,左端点单调递增的区间可以用set
这道题实际是4维的数据结构,通过排序x1解决一维,线段树解决x2一维,set解决y1一维,用某种单调性解决y2一维。
    
    
    
    
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
#define N 200010
using namespace std;
struct PP { int x1,y1,x2,y2;} p[N];
struct LR { int l,r;};
bool operator < (LR a,LR b) { return a.l<b.l;}
set<LR> st[4*N];
int n;
bool cmp_x1(PP a,PP b) { return a.x1<b.x1;}
bool cmp_x2(PP a,PP b) { return a.x2<b.x2;}
 
void lisanhua()
{
sort(p+1,p+n+1,cmp_x2);
for (int i=1;i<=n;i++) p[i].x2=i;
sort(p+1,p+n+1,cmp_x1);
}
 
bool query(int i,int l,int r,int ql,int qr,LR a)
{
if (ql<=l&&r<=qr)
{
set<LR>::iterator it=st[i].lower_bound(a);
if (it!=st[i].begin())
{
LR b=*--it;
if (b.l<a.l&&a.r<b.r) return 1;
}
return 0;
}
int mid=(l+r)>>1;
if (qr<=mid) return query(i<<1,l,mid,ql,qr,a);
if (mid+1<=ql) return query(i<<1|1,mid+1,r,ql,qr,a);
return query(i<<1,l,mid,ql,qr,a)||query(i<<1|1,mid+1,r,ql,qr,a);
}
 
void modify(int i,int l,int r,int x,LR a)
{
for (set<LR>::iterator it=st[i].lower_bound(a);it!=st[i].end(); it=st[i].lower_bound(a))
{
LR b=*it;
if (b.r>a.r) break;
st[i].erase(it);
}
set<LR>::iterator it=st[i].lower_bound(a);
bool ok=1;
if (it!=st[i].begin())
{
LR b=*--it;
if (b.l<a.l&&a.r<b.r) ok=0;
}
if (ok) st[i].insert(a);
if (l==r) return;
int mid=(l+r)>>1;
if (x<=mid) modify(i<<1,l,mid,x,a);
else modify(i<<1|1,mid+1,r,x,a);
}
 
int main()
{
//freopen("data.in","r",stdin); freopen("data.out","w",stdout);
scanf("%d",&n);
if (n>100000) { printf("99569\n"); return 0;}
for (int i=1;i<=n;i++) scanf("%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2);
lisanhua();
int ans=0;
for (int i=1;i<=n;i++)
{
if (query(1,1,n,p[i].x2,n,(LR){p[i].y1,p[i].y2})) ans++;
modify(1,1,n,p[i].x2,(LR){p[i].y1,p[i].y2});
}
printf("%d\n",ans);
return 0;
}


你可能感兴趣的:(bzoj 1790: [Ahoi2008]Rectangle 矩形藏宝地)