Codeforces 755 F. PolandBall and Gifts (简单贪心+二进制优化多重背包)
2017-08-29 13:23
447 查看
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 p, pi ≠ 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:
Ball number i will bring the present he should give.
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 i, pi ≠ 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
output
input
output
Note
In the first sample, if the third and the first balls will forget to bring their presents, they will be th only balls not getting a present. Thus the minimum answer is 2.
However, if the first ans the second balls will forget to bring their presents, then only the fifth ball will get a present. So, the maximum answer is 4.
题意:
这是一个带礼物的置换,只有当你给带了礼物且给你带礼物的那个人带了礼物你才能获得礼物,现在有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直接贪心就好;
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <bitset>
using namespace std;
const int maxn = 1e6 + 5;
int a[maxn], book[maxn], w[maxn], num[maxn], val[maxn];
bitset<maxn> dp;
int main()
{
int n, k, tot = 0, totl = 0, maxans = 0, minans = 0;
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 1; i <= n; i++)
{
int index = i, cnt = 0;
while(!book[index])
{
book[index] = 1;
index = a[index];
cnt++;
}
if(!cnt) continue;
if(num[cnt]) num[cnt]++;
else w[++tot] = cnt, num[cnt] = 1;
}
for(int i = 1; i <= tot; i++)
maxans += w[i] / 2 * num[w[i]];
if(maxans >= k) maxans = k*2;
else maxans = maxans*2 + k - maxans;
maxans = min(maxans, n); //这里要判断下, 是不是大于了总人数。。wa了几发。。
for(int i = 1; i <= tot; i++)
{
for(int k = 1; k <= num[w[i]]; k<<=1)
{
val[++totl] = k*w[i];
num[w[i]] -= k;
}
if(num[w[i]] > 0)
val[++totl] = num[w[i]]*w[i];
}
dp.set(0);
for(int i = 1; i <= totl; i++)
dp |= (dp << val[i]);
if(dp.test(k))
printf("%d %d\n", k, maxans);
else
printf("%d %d\n", k+1, maxans);
return 0;
}
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 p, pi ≠ 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:
Ball number i will bring the present he should give.
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 i, pi ≠ 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
Note
In the first sample, if the third and the first balls will forget to bring their presents, they will be th only balls not getting a present. Thus the minimum answer is 2.
However, if the first ans the second balls will forget to bring their presents, then only the fifth ball will get a present. So, the maximum answer is 4.
题意:
这是一个带礼物的置换,只有当你给带了礼物且给你带礼物的那个人带了礼物你才能获得礼物,现在有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直接贪心就好;
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <bitset>
using namespace std;
const int maxn = 1e6 + 5;
int a[maxn], book[maxn], w[maxn], num[maxn], val[maxn];
bitset<maxn> dp;
int main()
{
int n, k, tot = 0, totl = 0, maxans = 0, minans = 0;
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 1; i <= n; i++)
{
int index = i, cnt = 0;
while(!book[index])
{
book[index] = 1;
index = a[index];
cnt++;
}
if(!cnt) continue;
if(num[cnt]) num[cnt]++;
else w[++tot] = cnt, num[cnt] = 1;
}
for(int i = 1; i <= tot; i++)
maxans += w[i] / 2 * num[w[i]];
if(maxans >= k) maxans = k*2;
else maxans = maxans*2 + k - maxans;
maxans = min(maxans, n); //这里要判断下, 是不是大于了总人数。。wa了几发。。
for(int i = 1; i <= tot; i++)
{
for(int k = 1; k <= num[w[i]]; k<<=1)
{
val[++totl] = k*w[i];
num[w[i]] -= k;
}
if(num[w[i]] > 0)
val[++totl] = num[w[i]]*w[i];
}
dp.set(0);
for(int i = 1; i <= totl; i++)
dp |= (dp << val[i]);
if(dp.test(k))
printf("%d %d\n", k, maxans);
else
printf("%d %d\n", k+1, maxans);
return 0;
}
相关文章推荐
- Codeforces 755 F. PolandBall and Gifts 多重背包+贪心
- Codeforces 755-B. PolandBall and Game(贪心)
- 【codeforces 755F】PolandBall and Gifts
- 【Codeforces 755 C PolandBall and Forest】+ 并查集
- Codeforces 755-D. PolandBall and Polygon(树状数组+计算几何)
- codeforces 755 d PolandBall and Polygon(找规律)
- codeforces-755-B PolandBall and Game
- coderforces-755-C PolandBall and Forest(简单并查集)
- Codeforces 755-C. PolandBall and Forest(交互式题)
- 【Codeforces 755 B PolandBall and Game】
- Codeforces 676D - Theseus and labyrinth 【BFS(二进制优化迷宫旋转)】
- Codeforces #277.5 (Div. 2) C. Given Length and Sum of Digits...(简单贪心)
- Codeforces 755D-PolandBall and Polygon
- 【codeforces 755E】PolandBall and White-Red graph
- 【codeforces 755D】PolandBall and Polygon
- 【codeforces 755C】PolandBall and Forest
- Codeforces 106C Buns - 多重背包 - 二进制优化模板
- 【codeforces 755B】PolandBall and Game
- 【codeforces 755A】PolandBall and Hypothesis
- codeforces-755D-PolandBall and Polygon(数学题)