题目大意:
有 n n n 个人,每人有属性 l i , v i , r i ( l i ≤ v i ≤ r i ) l_i,v_i,r_i(l_i\leq v_i\leq r_i) li,vi,ri(li≤vi≤ri),要求选出最大的人的集合 S S S 使得 ∀ x , y ∈ S \forall x,y\in S ∀x,y∈S 有 l y ≤ v x ≤ r y l_y\leq v_x\leq r_y ly≤vx≤ry
题解:
简单分析一下这些不等式可以发现题目的要求可以转化为: max i ∈ S l i ≤ min i ∈ S v i ≤ max i ∈ S v i ≤ min i ∈ S r i \max\limits_{i\in S} l_i\leq \min\limits_{i\in S} v_i\leq \max\limits_{i\in S} v_i\leq\min\limits_{i\in S} r_i i∈Smaxli≤i∈Sminvi≤i∈Smaxvi≤i∈Sminri
进一步地,我们将要求转化为找到 L , R L,R L,R,使得 max i ∈ S l i ≤ L ≤ min i ∈ S v i , max i ∈ S v i ≤ R ≤ min i ∈ S r i \max\limits_{i\in S} l_i\leq L\leq \min\limits_{i\in S} v_i,\max\limits_{i\in S} v_i\leq R\leq\min\limits_{i\in S} r_i i∈Smaxli≤L≤i∈Sminvi,i∈Smaxvi≤R≤i∈Sminri
我们将 ( L , R ) (L,R) (L,R) 看作二维平面上的一个点,一个人就对应着一个矩形。集合中选出多个人,对 ( L , R ) (L,R) (L,R) 的限制就是这些矩形的交。选出最多的人,就是要找到一个点被尽可能多的矩形覆盖。
以样例为例
4
2 8 9
1 4 7
3 6 8
5 8 10
找到这个点可以用扫描线+线段树。记录最优的点的位置,输出方案时挨个判断矩形是否包含该点。
#include<bits/stdc++.h>
using namespace std;
inline int getint(){
int ans=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ans=ans*10+c-'0';
c=getchar();
}
return ans*f;
}
const int N=200100,M=600300;
int a[M<<2],tag[M<<2],pos[M<<2];
inline void pushup(int x){
if(a[x<<1]>a[x<<1|1]){
pos[x]=pos[x<<1];
a[x]=a[x<<1];
}else{
pos[x]=pos[x<<1|1];
a[x]=a[x<<1|1];
}
}
inline void pushdown(int x){
tag[x<<1]+=tag[x];
a[x<<1]+=tag[x];
tag[x<<1|1]+=tag[x];
a[x<<1|1]+=tag[x];
tag[x]=0;
}
void modify(int l,int r,int val,int x,int nl,int nr){
pushdown(x);
if(l<=nl&&nr<=r){
a[x]+=val;
tag[x]+=val;
return;
}
int mid=nl+nr>>1;
if(nl<=r&&mid>=l)modify(l,r,val,x<<1,nl,mid);
if(mid+1<=r&&nr>=l)modify(l,r,val,x<<1|1,mid+1,nr);
pushup(x);
}
inline int query(){
return a[1];
}
void build(int x,int l,int r){
if(l==r){
pos[x]=l;
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pos[x]=pos[x<<1];
}
int l[N],r[N],v[N];
struct seg{
int x,u,d;
bool b;
};
seg s[N];
bool cmp(seg a,seg b){
if(a.x!=b.x)return a.x<b.x;
else return a.b<b.b;
}
int main(){
int n=getint();
for(int i=0;i<n;i++){
l[i]=getint();
v[i]=getint();
r[i]=getint();
s[i*2].x=l[i]; s[i*2].u=r[i]; s[i*2].d=v[i]; s[i*2].b=0;
s[i*2+1].x=v[i]; s[i*2+1].u=r[i]; s[i*2+1].d=v[i]; s[i*2+1].b=1;
}
build(1,1,3e5+1);
sort(s,s+n*2,cmp);
int ans=0,ansp=0,ansx=0;
for(int i=0;i<n*2;i++){
modify(s[i].d,s[i].u,s[i].b?-1:1,1,1,3e5+1);
if(query()>ans){
ans=query();
ansp=pos[1];
ansx=s[i].x;
}
}
cout<<ans<<endl;
for(int i=0;i<n;i++){
if(l[i]<=ansx&&ansx<=v[i]&&v[i]<=ansp&&ansp<=r[i])cout<<i+1<<" ";
}
return 0;
}