组队

  题目:

   现在辛辛想要组一只队伍去屠杀巨龙,每个人都有一个能力值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;
}

 

posted @ 2019-06-28 17:09  paopo  阅读(298)  评论(0编辑  收藏  举报