苹果(apple)二分答案+贪心判定

苹果(apple)
【题目背景】
尽管题目名是苹果,但是此题和苹果没有任何关系。
这是为什么呢?
【题目描述】
考虑一个树形结构的信号传递网络,初始存在一个信号源点,记其标号为 0。
树上有两种节点,一种为信号中继点,用来接收父亲节点的信号并分发给它的儿子
们。另一种为信号接收点,仅能接收父亲节点的信号但不能向下传递。
对于一个中继点 i ,它能最多将信号分发给 ai 个儿子。对于一个接收点 i,它能生
效仅当它与初始源点间的中继点个数不超过 bi。
对于 bi = 0 的接收点,只能直接连接在源点上。源点可以视作一种特殊的中继点,
它仅能将信号分发给 1 个儿子。
现在给出 n 个中继点和 m 个接收点,小 Z 想知道最多可以使多少个接收点接受到
信号。
注意你不. 一. 定. 需要使用所有 n + m 个节点。
【输入格式】
从文件 apple.in 中读入数据。
输入的第一行包含两个正整数 n, m,保证 1 ≤ n, m ≤ 2 · 105,含义如上所述。
输入的第二行包含 n 个正整数 a1, a2, ..., an,表示 n 个中继点。2 ≤ ai ≤ 2 · 105
输入的第三行包含 m 个正整数 b1, b2, ..., bm,表示 m 个接收点。0 ≤ bi ≤ 2 · 105
【输出格式】
输出到文件 apple.out 中。
输出一行一个正整数,表示最多可以使多少个接收点接受到信号。
【样例 1 输入】
3 6
4 2 2
1 2 3 2 1 1
【样例 1 输出】
5
【样例 2】
见选手目录下的 apple/apple2.in 与 apple/apple2.ans。
【子任务】
测试点 n m 特殊性质
1 ≤ 3 ≤ 3 无
2 ≤ 10 ≤ 10 无
3 ≤ 20 ≤ 20 无
4 ≤ 20 ≤ 20 bi = i
5 ≤ 200000 ≤ 200000 bi 互不相同
6 ≤ 200000 ≤ 200000 ai = 2
7 ≤ 50000 ≤ 50000 无
8 ≤ 200000 ≤ 200000 无
9 ≤ 200000 ≤ 200000 无
10 ≤ 200000 ≤ 200000 无

题解见注释

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 2 * 100000 + 10 ;
int n,m,a[maxn],b[maxn],ans,now[maxn];
bool cmp(int x,int y){return x>y;}
//贪心策略 先放不得不放的接收器 ,在选择分发能力强的中继器 
bool judge(int x)
{
    memset(now,0,sizeof(now));
    int top(0),flor(1);now[flor]=1;
    for(;;){
        while(x && now[flor] && b[x]<flor) x--,now[flor]--;//如果还有剩余位置,且还有接收七器 
        if(!x)           return true;//如果所有接收器都用了,二分的答案可行; 
        if(x && !now[flor]) return false; //如果还有剩的接收器,且没有剩余位置了,不可行 
        while(now[flor] && top<n)//统计这层的位置放入中继器,统计下层位置 
            now[flor+1]+=a[++top],now[flor]--;
        now[flor+1]+=now[flor];//下层位置加上这层还还剩的位置 
        flor++;
    }
}
int main()
{
    freopen("apple.in","r",stdin);
    freopen("apple.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    sort(a+1,a+1+n,cmp);//从大到小排序 ,贪心得想,二分选的接收器可大的来; 
    sort(b+1,b+m+1,cmp);
    int l=1,r=m;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(judge(mid)) l=mid+1,ans=mid;
        else           r=mid;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hfang/p/11622175.html