377D Developing Game(线段树+扫描线)
题意:有n个开发人员,每个人有个技能值vi,每个人不想和技能值不在区间[li,ri]的人合作,现在要选尽可能多的人,使得满足所有选中的人的要求。
思路:首先,如果我们能求出一组L,R,使得每个选中的人i都满足li<=L<=R<=ri并且L<=vi<=R,那么我们就能找到应该选出的人。那么如何求这个L和R呢,把L,R想象成坐标系中的一个点,那么对于每一个人,需要满足li<=L<=vi并且vi<=R<=ri,这样,每个人可以看成一个矩形,问题就变成了寻找一个点使得有最多的矩形覆盖,这个问题可以用线段树+扫描线处理。
代码:

#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , mid
#define rson rs , mid + 1 , r
#define root 1 , 1 , n
#define rt o , l , r
vector <int> v1[300005],v2[300005];
int L[100005],V[100005],R[100005];
int N,ans;
int a,b;
struct node
{
int x,w,c;//c表示子节点是否需要更新,0表示不用,
//w存的是当前节点的最左端,x表示最大的覆盖数
}s[1<<20];
void build (int o , int l , int r)
{
s[o].c = s[o].x = 0;
if (l == r)
{
s[o].w = l;
return;
}
int mid = ( l + r ) >> 1;
build(lson);
build(rson);
s[o].w = s[ls].w;
}
void pushdown(int o)
{
s[ls].x += s[o].c;
s[rs].x += s[o].c;
s[ls].c += s[o].c;
s[rs].c += s[o].c;
s[o].c = 0;
}
void update(int o , int l , int r , int le , int re , int v)
{
if(l <= le && re <= r)
{
s[o].x += v;
s[o].c += v;
return ;
}
if(s[o].c != 0) pushdown(o);
int mid = ( le + re ) >> 1;
if(r > mid)
update(rs, l, r , mid+1 , re , v);
if(l <= mid)
update(ls, l, r , le , mid , v);
if(s[ls].x < s[rs].x)
{
s[o].x = s[rs].x;
s[o].w = s[rs].w;
}
else
{
s[o].x = s[ls].x;
s[o].w = s[ls].w;
}
}
int main()
{
scanf("%d",&N);
for(int i=0; i<N; i++)
{
scanf("%d%d%d",L+i,V+i,R+i);
v1[L[i]].push_back(i);
v2[V[i]].push_back(i);
}
build(1,1,3e5);
for(int i=1; i<=3e5; i++)
{
for(int j=0; j<v1[i].size(); j++)
{
update(1,V[v1[i][j]],R[v1[i][j]],1,3e5,1);
//printf("i=%d , v1=%d , V=%d , R=%d\n",i,v1[i][j],V[v1[i][j]],R[v1[i][j]]);
}
if(ans<s[1].x)
{
ans=s[1].x, a=i, b=s[1].w;
//printf("ans=%d , a=%d , b=%d\n",ans,a,b);
}
for(int j=0; j<v2[i].size(); j++)
{
update(1,i,R[v2[i][j]],1,3e5,-1);
//printf("i=%d , v2=%d , i=%d , R=%d\n",i,v2[i][j],V[v2[i][j]],R[v2[i][j]]);
}
}
printf("%d\n",ans);
for(int i=0; i<N; i++)
{
if(L[i]<=a&&a<=V[i]&&V[i]<=b&&b<=R[i])
printf("%d ",i+1);
}
return 0;
}
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , mid
#define rson rs , mid + 1 , r
#define root 1 , 1 , n
#define rt o , l , r
vector <int> v1[300005],v2[300005];
int L[100005],V[100005],R[100005];
int N,ans;
int a,b;
struct node
{
int x,w,c;//c表示子节点是否需要更新,0表示不用,
//w存的是当前节点的最左端,x表示最大的覆盖数
}s[1<<20];
void build (int o , int l , int r)
{
s[o].c = s[o].x = 0;
if (l == r)
{
s[o].w = l;
return;
}
int mid = ( l + r ) >> 1;
build(lson);
build(rson);
s[o].w = s[ls].w;
}
void pushdown(int o)
{
s[ls].x += s[o].c;
s[rs].x += s[o].c;
s[ls].c += s[o].c;
s[rs].c += s[o].c;
s[o].c = 0;
}
void update(int o , int l , int r , int le , int re , int v)
{
if(l <= le && re <= r)
{
s[o].x += v;
s[o].c += v;
return ;
}
if(s[o].c != 0) pushdown(o);
int mid = ( le + re ) >> 1;
if(r > mid)
update(rs, l, r , mid+1 , re , v);
if(l <= mid)
update(ls, l, r , le , mid , v);
if(s[ls].x < s[rs].x)
{
s[o].x = s[rs].x;
s[o].w = s[rs].w;
}
else
{
s[o].x = s[ls].x;
s[o].w = s[ls].w;
}
}
int main()
{
scanf("%d",&N);
for(int i=0; i<N; i++)
{
scanf("%d%d%d",L+i,V+i,R+i);
v1[L[i]].push_back(i);
v2[V[i]].push_back(i);
}
build(1,1,3e5);
for(int i=1; i<=3e5; i++)
{
for(int j=0; j<v1[i].size(); j++)
{
update(1,V[v1[i][j]],R[v1[i][j]],1,3e5,1);
//printf("i=%d , v1=%d , V=%d , R=%d\n",i,v1[i][j],V[v1[i][j]],R[v1[i][j]]);
}
if(ans<s[1].x)
{
ans=s[1].x, a=i, b=s[1].w;
//printf("ans=%d , a=%d , b=%d\n",ans,a,b);
}
for(int j=0; j<v2[i].size(); j++)
{
update(1,i,R[v2[i][j]],1,3e5,-1);
//printf("i=%d , v2=%d , i=%d , R=%d\n",i,v2[i][j],V[v2[i][j]],R[v2[i][j]]);
}
}
printf("%d\n",ans);
for(int i=0; i<N; i++)
{
if(L[i]<=a&&a<=V[i]&&V[i]<=b&&b<=R[i])
printf("%d ",i+1);
}
return 0;
}


浙公网安备 33010602011771号