组队
题目:
现在辛辛想要组一只队伍去屠杀巨龙,每个人都有一个能力值ai,而如果两个人之间的能力值差距过大,那么两个人就无法交流,然而每个人的沟通能力也是不同的,具体来讲,每个人只能接受能力值在[li,ri]内的人做他的队友。
辛辛想要多交朋友,所以他想让队伍里的人数尽可能的多,请你输出这个最多的人数。
对于10%的数据,n<=20;
对于另外10%的数据,n<=300;
对于另外20%的数据,n<=1000;
对于100%的数据,n<=1e5,1<=li<=ai<=ri<=3e5。、
可以利用扫描线线段树来做。
一个队伍中的L,R一定满足所有的 l i < = L < = a < = R < = r i 。所以我们将每一个人在平面直角坐标系上看成一个矩形,横坐标为 l i 到 a i ,纵坐标为 a i 到 r i ,那么在矩形内部的(L , R),对于这个人就可以作为一个合法的L,R。所以我们就要找到一个(不一定唯一)坐标 ( L , R ) ,使得在这个点在尽量多的矩形内。
那我们就枚举纵坐标从小到大,对于矩形下下方的那一条边,对于这个矩形 l i ,a i ,我们在线段树上将这一段区间加1,,若是在矩形上面的边+1,就区间- 1 。每一次操作后计算去找最大值(某个区间最多在多少矩形里),更新即可。
有个要注意的地方:
重载运算符时先减后加,因为每一次我们都统计答案,不能使本该已经被减去的部分,还没减去就统计最大值,这样结果会偏大。(感谢良心数据)
代码:
#include<cstdio> #include<iostream> #include<queue> #include<iostream> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define maxn 300005*4 #define ls now<<1 #define rs now<<1|1 int l[maxn],r[maxn],lazy[maxn],sum[maxn],M[maxn]; struct node { int h,L,R,op; friend bool operator < (node a,node b) { if(a.h==b.h) return a.op > b.op; return a.h > b.h; } } e; priority_queue<node> Q; int n,m; void pushdown(int now) { if(!lazy[now]) return ; lazy[ls]+=lazy[now]; lazy[rs]+=lazy[now]; sum[ls]+=lazy[now]*(r[ls]-l[ls]+1); sum[rs]+=lazy[now]*(r[rs]-l[rs]+1); M[ls]+=lazy[now]; M[rs]+=lazy[now]; lazy[now]=0; return ; } void up(int now) { M[now]=max(M[ls],M[rs]); sum[now]=sum[ls]+sum[rs]; } void build(int L,int R,int now) { l[now]=L; r[now]=R; if(L==R) return ; int mid=(L+R)>>1; build(L,mid,ls); build(mid+1,R,rs); } void update(int now,int L,int R,int x) { if(L==l[now]&&R==r[now]) { lazy[now]+=x; sum[now]+=x*(R-L+1); M[now]+=x; return ; } pushdown(now); int mid=(l[now]+r[now])>>1; if(R<=mid) update(ls,L,R,x); else if(L>mid) update(rs,L,R,x); else { update(ls,L,mid,x); update(rs,mid+1,R,x); } up(now); } int main() { freopen("team.in","r",stdin); freopen("team.out","w",stdout); scanf("%d",&n); for(int i=1; i<=n; i++) { int L,a,R; scanf("%d%d%d",&L,&a,&R); e.L=L; e.R=a; e.h=a; e.op=1; Q.push(e); e.h=R+1; e.op=-1; Q.push(e); m=max(m,a); } build(1,m,1); int ans=0; while(!Q.empty()) { e=Q.top(); Q.pop(); update(1,e.L,e.R,e.op); ans=max(ans,M[1]); } printf("%d\n",ans); return 0; }