习题: Developing Game(扫描线&线段树)
题目
思路
我们考虑怎么将转换这个限制
考虑最终的答案一定满足一个式子,对于方案中的任意一个人都满足\(l_i<=min\{v_i\}<=v_i<=max\{v_i\}<=r_i\)
我们把平面内的每一个点看做\((min\{v_i\},max\{v_i\})\)
把其转换成为一个矩阵,矩阵的左下角的左边即为\((l_i,v_i)\),右上角的坐标即为\((v_i,r_i)\),
之后就是求最多有多少个矩阵重叠在一起,这就是一个扫描线的板子了
代码
#include<iostream>
#include<vector>
using namespace std;
namespace lst
{
struct node
{
int l,r;
int maxx,lazy,_ind;
}tre[1200005];
void build(int l,int r,int k)
{
tre[k].l=l;
tre[k].r=r;
if(l==r)
{
tre[k]._ind=l;
return;
}
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
tre[k].maxx=max(tre[k<<1].maxx,tre[k<<1|1].maxx);
tre[k]._ind=(tre[k].maxx==tre[k<<1].maxx?tre[k<<1]._ind:tre[k<<1|1]._ind);
}
void push_down(int k)
{
tre[k<<1].lazy+=tre[k].lazy;
tre[k<<1].maxx+=tre[k].lazy;
tre[k<<1|1].lazy+=tre[k].lazy;
tre[k<<1|1].maxx+=tre[k].lazy;
tre[k].lazy=0;
}
void change(int l,int r,int val,int k=1)
{
if(l>tre[k].r||tre[k].l>r)
return;
if(l<=tre[k].l&&tre[k].r<=r)
{
tre[k].maxx+=val;
tre[k].lazy+=val;
return;
}
push_down(k);
change(l,r,val,k<<1);
change(l,r,val,k<<1|1);
tre[k].maxx=max(tre[k<<1].maxx,tre[k<<1|1].maxx);
tre[k]._ind=(tre[k].maxx==tre[k<<1].maxx?tre[k<<1]._ind:tre[k<<1|1]._ind);
}
}
using namespace lst;
struct NODE
{
int l,v,r;
}a[100005];
struct ls
{
int l,r;
};
int n;
int maxx,limit,ans;
pair<int,int> li;
vector<ls> ad[300005];
vector<ls> de[300005];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].l>>a[i].v>>a[i].r;
maxx=max(a[i].v,maxx);
limit=max(a[i].r,limit);
ad[a[i].l].push_back((ls){a[i].v,a[i].r});
de[a[i].v].push_back((ls){a[i].v,a[i].r});
}
build(1,limit,1);
for(int i=1;i<=maxx;i++)
{
for(int j=0;j<ad[i].size();j++)
change(ad[i][j].l,ad[i][j].r,1);
for(int j=0;j<de[i-1].size();j++)
change(de[i-1][j].l,de[i-1][j].r,-1);
if(tre[1].maxx>ans)
{
ans=tre[1].maxx;
li=make_pair(i,tre[1]._ind);
}
}
int f=1;
cout<<ans<<'\n';
for(int i=1;i<=n;i++)
{
if(a[i].l<=li.first&&li.first<=a[i].v&&a[i].v<=li.second&&li.second<=a[i].r)
{
if(f)
{
cout<<i;
f=0;
}
else
cout<<' '<<i;
}
}
return 0;
}

浙公网安备 33010602011771号