用线段树做这题至少有两种写法
输入数据的离散,建树,求每个离散后的纵坐标穿过的矩形数都一样,不同的地方在遍历纵坐标求答案。
线段树存的是lazy标记和区间内最大值
1.输入矩形的横坐标没用,只要储存纵坐标。坐标范围达到10的7次方,故先离散化。把每个矩形表示成纵坐标对应的线段即可
2.在线段树中把这些区间值加一(建树),注意要用lazy标记,顺便分别求出以每个点为起点、终点的线段是哪些(这里可以开两个比较大(200010)的vector数组 )。
3.查询每个点的值并存入数组ans[]内,即离散后每个纵坐标(其实已经是线段的端点了)穿过的矩阵数。
接下来要遍历所有线段的两个端点并找到最大的答案,此时有两种写法:
一种是从前往后遍历每个点,先把以该点(i)为起点的线段从树中删去(即区间值减一),此时tree[1].max(线段树最大区间内的最大值)+ans[i]即为可能的答案,最后把以该点(i)为终点的线段加入树中(即区间值加一),本次操作结束。
取每次循环得到的答案的最大值即为结果。这种写法保证遍历每个点的时候已经把该点穿过的矩阵删去,故tree[1].max可以表示其他点的最大穿过数。
另外一种也是从前往后遍历每个点,不同的是只把以该点(i)为起点的线段从树中删去,查询查从i到最后一个点的最大值,查询结果+ans[i]为可能的答案,不需要把以该点(i)为终点的线段加入树中(即区间值加一)。
同样取每次循环得到的答案的最大值即为结果。但是这种写法利用了从前往后遍历的性质,只考虑i和i后面的点即可,因为i和i前面的点已经在之前出现过了。
本文给出第一种写法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int ux[100010],uy[100010],dis[200010],con=1,ans[200010];
vector<int>gl[200010],gr[200010];
struct node
{
int m,f;
}tree[800010];
void pushdown(int now,int l,int r)
{
tree[l].m+=tree[now].f;
tree[r].m+=tree[now].f;
tree[l].f+=tree[now].f;
tree[r].f+=tree[now].f;
tree[now].f=0;
}
void change(int l,int r,int now,int x,int y,int h)
{
if(x<=l&&r<=y)
{
tree[now].f+=h;
tree[now].m+=h;
return;
}
int mid=(l+r)>>1;
if(tree[now].f)
pushdown(now,now<<1,now<<1|1);
if(y<=mid)
change(l,mid,now<<1,x,y,h);
else if(x>mid)
change(mid+1,r,now<<1|1,x,y,h);
else
{
change(l,mid,now<<1,x,mid,h);
change(mid+1,r,now<<1|1,mid+1,y,h);
}
tree[now].m=max(tree[now<<1].m,tree[now<<1|1].m);
}
int query(int l,int r,int now,int x)
{
if(l==r)
return tree[now].m;
if(tree[now].f)
pushdown(now,now<<1,now<<1|1);
int mid=(l+r)>>1;
if(x<=mid)
return query(l,mid,now<<1,x);
else
return query(mid+1,r,now<<1|1,x);
}
int main()
{
// freopen("1.txt","r",stdin);
int n;
cin>>n;
for(int i=1;i<=n;++i)
{
int a;
scanf("%d%d%d%d",&a,&uy[i],&a,&ux[i]);
dis[con++]=uy[i];
dis[con++]=ux[i];
}
sort(dis+1,dis+con);
con=unique(dis+1,dis+con)-dis-1;
for(int i=1;i<=n;++i)
{
ux[i]=lower_bound(dis+1,dis+con+1,ux[i])-dis;
uy[i]=lower_bound(dis+1,dis+con+1,uy[i])-dis;
gl[ux[i]].push_back(i);
gr[uy[i]].push_back(i);
change(1,con,1,ux[i],uy[i],1);
}
for(int i=1;i<=con;++i)
{
ans[i]=query(1,con,1,i);
}
int Max=0;
for(int i=1;i<=con;++i)
{
for(int j=0;j<gl[i].size();++j)
change(1,con,1,ux[gl[i][j]],uy[gl[i][j]],-1);
Max=max(Max,ans[i]+tree[1].m);
for(int j=0;j<gr[i].size();++j)
change(1,con,1,ux[gr[i][j]],uy[gr[i][j]],1);
}
printf("%d\n",Max);
return 0;
}