Codeforces Round #521 (Div. 3)

题目链接:http://codeforces.com/contest/1077

A.Frog Jumping

解题思路:作差再判断最后是否还要向右跳一次即可。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 LL T,a,b,k;
 5 int main(){
 6     while(cin>>T){
 7         while(T--){
 8             cin>>a>>b>>k;
 9             cout<<(a-b)*(k/2)+(k%2?a:0)<<endl;
10         }
11     }
12     return 0;
13 }
B.Disturbed People

解题思路:题意已说得很清楚了,只要找到满足a[i-1]==1&&a[i]==0&&a[i+1]==1,那么就关掉第i-1和第i+1间房间的灯(其状态值改为0),若满足条件--->i+=3,表示当前的灯已熄灭,只需站到第i+3间房间继续检查即可。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 int n,cnt,a[105];
 5 int main(){
 6     while(cin>>n){
 7         cnt=0;
 8         for(int i=0;i<n;++i)cin>>a[i];
 9         for(int i=1;i<n-1;){
10             if(a[i-1]&&!a[i]&&a[i+1])cnt++,i+=3;
11             else i++;
12         }
13         cout<<cnt<<endl;
14     }
15     return 0;
16 }
C.Good Array

解题思路:统计所有元素之和:sum,然后枚举每个元素,令tmp=(sum-a[i])>>1表示原数组删去a[i]后剩余元素之和的一半,由"好的数组"定义可知,如果(sum-a[i])为奇数,则剩下的元素肯定不能分成相等的两部分;否则只需检查tmp是否在剩下的元素当中,若是则归纳答案!

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn=2e5+5;
 5 int n,k,b[maxn];LL a[maxn],sum,tmp;map<LL,int> mp;
 6 int main(){
 7     while(~scanf("%d",&n)){
 8         sum=0,k=0;mp.clear();
 9         for(int i=1;i<=n;++i)scanf("%lld",&a[i]),sum+=a[i],mp[a[i]]++;///要用map或一维数组记录每个数字出现的次数,不能用set容器
10         for(int i=1;i<=n;++i){
11             if((sum-a[i])&1LL)continue;///奇数则跳过
12             tmp=(sum-a[i])>>1;
13             mp[a[i]]--;///先删去该元素
14             if(mp[tmp])b[k++]=i;
15             mp[a[i]]++;///再添加该元素
16         }
17         printf("%d\n",k);
18         if(!k)puts("");
19         for(int i=0;i<k;++i)printf("%d%c",b[i],(i==k-1)?'\n':' ');
20     }
21     return 0;
22 }
D.Cutting Out

解题思路:题目要求找出k个元素组成的集合t,使得每次删去集合s中包含t集合中的k个元素,并且最大化删除的次数,典型的二分查找答案!先统计每个元素出现的次数cnt_i,再通过二分查找最大化删除的次数z,二分条件为∑cnt_i/z≥k,如果为True,则向右找更大的删除次数,否则向左找较小的删除次数,最后每个元素被挑选的个数就为cnt_i/z',简单输出集合t中的k个元素即可。

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include <map>
 4 #include <vector>
 5 using namespace std;
 6 typedef long long LL;
 7 int n, k, x, l, r, mid, t;
 8 map<int, int> mp;
 9 vector<int> ans, cnt;
10 bool check(int z){
11     int sum = 0;
12     for (auto num : cnt)sum += num / z;
13     return sum >= k;
14 }
15 int main(){
16     while (~scanf("%d%d", &n, &k)){
17         mp.clear(), ans.clear(), cnt.clear(); l = 1, r = n;
18         for (int i = 0; i < n; ++i)scanf("%d", &x), mp[x]++;
19         for (auto y : mp)cnt.push_back(y.second);///保存对应数字出现的次数
20         while (l <= r){///二分查找要切的最大次数
21             mid = (l + r) >> 1;
22             if (check(mid))l = mid + 1;///最大化往右边找
23             else r = mid - 1;
24         }
25         for (auto u : mp){
26             t = u.second / r;
27             while (t--)ans.push_back(u.first);///第i个元素一次需要取t个
28         }
29         for (int i = 0; i < k; ++i)printf("%d%c", ans[i], i == k - 1 ? '\n' : ' ');
30     }
31     return 0;
32 }

 

posted @ 2018-11-17 16:42  霜雪千年  阅读(261)  评论(0编辑  收藏  举报