zoukankan      html  css  js  c++  java
  • codeforces 755F F. PolandBall and Gifts(贪心+多重背包)

    题目链接:

    F. PolandBall and Gifts

    time limit per test
    1.5 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    It's Christmas time! PolandBall and his friends will be giving themselves gifts. There are n Balls overall. Each Ball has someone for whom he should bring a present according to some permutation ppi ≠ i for all i.

    Unfortunately, Balls are quite clumsy. We know earlier that exactly k of them will forget to bring their gift. A Ball number i will get his present if the following two constraints will hold:

    1. Ball number i will bring the present he should give.
    2. Ball x such that px = i will bring his present.

    What is minimum and maximum possible number of kids who will not get their present if exactly k Balls will forget theirs?

    Input

    The first line of input contains two integers n and k (2 ≤ n ≤ 106, 0 ≤ k ≤ n), representing the number of Balls and the number of Balls who will forget to bring their presents.

    The second line contains the permutation p of integers from 1 to n, where pi is the index of Ball who should get a gift from the i-th Ball. For all ipi ≠ i holds.

    Output

    You should output two values — minimum and maximum possible number of Balls who will not get their presents, in that order.

    Examples
    input
    5 2
    3 4 1 5 2
    output
    2 4
    input
    10 1
    2 3 4 5 6 7 8 9 10 1
    output
    2 2

    题意:

    这是一个带礼物的置换,只有当你给带了礼物且给你带礼物的那个人带了礼物你才能获得礼物,现在有k个人没带礼物,问最少和最多有多少人无法获得礼物;

    思路:

    先把这个置换写成循环的形式,对于一个长度为x的循环,现在假设其中y个没带礼物,那么最少会有y+1个人无法获得礼物,如果x==y,那么就有y个人无法获得礼物,最多有2*y个人没法获得礼物;
    所以现在答案的贪心条件就明晰了;
    假设这个置换可以写成num个循环,分别长为bi,那么其中一些bi的和等于k那么minans=k,or minans=k+1;这时发现是一个背包问题,可以发现bi的种类大约在sqrt(n)附近,
    所以像多重背包那样把bi的数目转化成二进制的和,这样复杂度就降下来了,还有多重背包可以用单调队列优化
    maxans直接贪心就好;

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+5;
    int n,k,vis[maxn],a[maxn],b[maxn],c[maxn],d[maxn];
    bool dp[maxn];
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        int ans1=k,ans2=0,cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(vis[i])continue;
            int number=0,p=i;
            while(!vis[p])
            {
                vis[p]=1;
                number++;
                p=a[p];
            }
            b[++cnt]=number;
        }
        sort(b+1,b+cnt+1);
        int kk=k,num=0;
        for(int i=1;i<=cnt;++i)
        {
            if(b[i]/2<=kk)ans2+=b[i]/2*2,kk-=b[i]/2;
            else ans2+=2*kk,kk=0;
            if(b[i]&1)num++;
        }
        ans2+=min(kk,num);
        num=0;
        int number=0;
        for(int i=1;i<=cnt;++i)
        {
            if(b[i]==b[i-1])d[num]++;
            else d[++num]=1,a[num]=b[i];
        }
        cnt=0;
        for(int i=1;i<=num;++i)
        {
            for(int j=1;d[i];j<<=1)
            {
                int tep=min(d[i],j);
                c[++cnt]=a[i]*tep;
                d[i]-=tep;
            }
        }
        dp[0]=true;
        for(int i=1;i<=cnt;++i)
            for(int j=k-c[i];j>=0;--j)
                if(dp[j])dp[j+c[i]]=true;
        if(!dp[k])ans1++;
        printf("%d %d
    ",ans1,ans2);
        return 0;
    }
    

      

  • 相关阅读:
    安装包报错2503解决方法
    js中return;、return true、return false;区别
    图片添加border 不占用图片的大小
    效果网址http://sc.chinaz.com/tag_jiaoben/tupianlunbo.html
    兼容ie8 rgba()用法
    html使用css让文字多行超出部分用省略号三个点显示的方法案例
    MyCat02--MyCat入门无ZK实践
    MyCat01--基础
    MySQL/MariaDB导入(load data infile)导出(select into outfile)
    MariaDB/Mysql临时表
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/6293323.html
Copyright © 2011-2022 走看看