GYM 100971 H.Pavel's Party(BIT)

来源:互联网 发布:iphone照片同步到mac 编辑:程序博客网 时间:2024/05/17 01:06

Description
一个人想邀请k个朋友来做客,给第i个朋友打电话他会告诉一个[ai,bi]表示包括这个人自己在内有ai到bi个人去这个人就会去,每次打电话都是从第一个朋友开始按顺序打,叫够k个人就不打电话了,问对1~n中每个k要打多少个电话恰能邀请到k个人
Input
第一行一整数n表示朋友数量,之后n行两个整数ai和bi表示该朋友去做客对人数的要求(1<=n<=2e5,1<=ai<=bi<=n)
Output
输出n个数表示k从1取到n时至少需要打多少电话才能叫到k个人,如果给n个人打电话后也叫不齐k个人则输出-1
Sample Input
6
3 3
1 2
3 6
3 4
1 4
4 6
Sample Output
2 5 4 6 -1 -1
Solution
对于每个要求[ai,bi]用两个二元组(ai,-i)和(bi,i)来表示,对这些二元组排序(第一维升序,第一维相等则第二维升序),对于每个k,把所有第一维不大于k第二维为负的二元组插到BIT中(这些二元组表示叫k个人做客时可以来的客人,插入的时候如果是第二维为-i则在i位置插入1表示这个人会来,如果第二维为i则在i位置插入-1表示这个人不会来),那么对任一x,在BIT中求一个1~x的前缀和就表示如果给前x个人打电话可以叫到多少人来做客,我们要求的是使得前缀和恰为k的x,那么我们从高往低给x的二进制位赋值,如果当前位赋为1后前缀和小于k则赋1否则赋0,那么我们得到了使得前缀和不大于k的最大x,如果1~x的前缀和小于k则给x加一,此时如果1~x的前缀和等于k说明给前x个人打电话即可,否则说明无解(这种情况就是当前BIT中所有数加起来小于k,也即给所有人打电话也叫不齐k个人),当对于一个k的答案求完之后,要把所有第一维不大于k第二维为正的二元组插到BIT中表示消除右端点小于等于k的人对后面答案的影响
Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define maxn 222222struct BIT{    #define lowbit(x) (x&(-x))    int b[maxn],n;    void init(int _n)    {        memset(b,0,sizeof(b));        n=_n;    }    void update(int x,int v)    {        while(x<=n)        {            b[x]+=v;            x+=lowbit(x);        }    }    int query(int x)    {        if(x>n)return INF;        int ans=0;        while(x)        {            ans+=b[x];            x-=lowbit(x);        }        return ans;    } }bit;typedef pair<int,int>P;P a[2*maxn];int n;int main(){    while(~scanf("%d",&n))    {        bit.init(n);        int res=0;        for(int i=1;i<=n;i++)        {            int l,r;            scanf("%d%d",&l,&r);            a[res++]=P(l,-i),a[res++]=P(r,i);        }        sort(a,a+res);        for(int k=1,cnt=0;k<=n;k++)        {            while(cnt<res&&a[cnt].second<0&&a[cnt].first<=k)bit.update(-a[cnt].second,1),cnt++;            int ans=0;            for(int i=(1<<18);i;i>>=1)                if(bit.query(ans|i)<k)ans|=i;            if(bit.query(ans)<k)ans++;            if(bit.query(ans)==k)printf("%d",ans);            else printf("-1");            printf("%c",k==n?'\n':' ');            while(cnt<res&&a[cnt].second>0&&a[cnt].first<=k)bit.update(a[cnt].second,-1),cnt++;        }    }    return 0;}
0 0
原创粉丝点击