Codeforces Round #673 (Div. 2)补题报告
A.Copy-paste
BThero is a powerful magician. He has got nn piles of candies, the ii-th pile initially contains aiai candies. BThero can cast a copy-paste spell as follows:
- He chooses two piles (i,j) such that1≤i,j≤n and i≠ji≠j.
- All candies from pile ii are copied into pile j. Formally, the operation aj:=aj+ai is performed.
BThero can cast this spell any number of times he wants to — but unfortunately, if some pile contains strictly more than kk candies, he loses his magic power. What is the maximum number of times BThero can cast the spell without losing his power?
The first line contains one integer T (1≤T≤500) — the number of test cases.
Each test case consists of two lines:
- the first line contains two integers nn and k (2≤n≤1000, 2≤k≤104);
- the second line contains nn integers a1, a2, ..., anan (1≤ai≤k).
It is guaranteed that the sum of nn over all test cases does not exceed 1000, and the sum of k over all test cases does not exceed 10e4.
For each test case, print one integer — the maximum number of times BThero can cast the spell without losing his magic power.
题目意思就是给一个数组,有一个操作aj:=aj+ai ,如果某个数超过k则终止且失效,对于这个问题,我们只需要先排序,然后对每个数用数组的第一个去加即可,因为如果有aj:=aj+ai <k那么把i加到j和j叫到i的操作等价,我们只需要保证这个a[i]始终最小就行。
#include<bits/stdc++.h> using namespace std; long long int a[1004]; int main() { int t,n,k,ans; cin>>t; while(t--) {ans=0; cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1); for(int i=2;i<=n;i++) ans+=(k-a[i])/a[1]; cout<<ans<<endl; } return 0; }
B. Two Arrays
题目大意为,给一个数组,我们可以把他分为2个数组,要保证让两个数组中能形成a[I]+a[j]==t的组合数最少。
解决这个问题我们只需要保证任意两个数尽可能少的拼成一个t。那么我们很容易发现当t为奇数时,我们把所有小于t/2的数放一起,大于t/2的数放一起,就不会有任何一个可能的组合满足条件。而当t为偶数时,会有=t/2的数的情况,我们只需要尽可能把这样的数分散到两个数组中即可。
#include<bits/stdc++.h> using namespace std; long long int a[100004]; int main() { long long int t,n,k,ans,flag; cin>>t; while(t--) { cin>>n>>k; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } if(k%2) { for(int i=1;i<=n;i++) { if(a[i]<=k/2)cout<<1<<" "; else cout<<0<<" "; } } else { flag=0; for(int i=1;i<=n;i++) { if(a[i]==k/2){ flag=1-flag; cout<<flag<<" "; } else if(a[i]<k/2) cout<<1<<" "; else cout<<0<<" "; } }cout<<endl; } return 0; }
C. k-Amazing Numbers
给你一个数组a,由n个从1到n的整数组成。
让我们将数组的k-惊人数定义为数组中所有长度为k的子段中出现的最小数(回想一下,长度为k的a的一个子段是a中包含k个元素的连续部分)。如果k的某个值在长度k的所有子段中都没有整数,那么k-惊人数是−1。
对于从1到n的每个k,计算数组a的k-惊人数。
输入
第一行包含一个整数t(1≤t≤1000)——测试用例的数量。接下来是t测试用例。
每个测试用例的第一行包含一个整数n(1≤n≤3⋅105),即数组中的元素数。第二行包含n个整数a1,a2,…,an(1≤ai≤n)-数组的元素。
保证所有测试用例的n之和不超过3⋅105。
输出
对于每个测试用例打印n个整数,其中第i个整数等于数组的i个惊人数。
在处理这个问题时,我们需要得到对于每一个长度,维护一个这个长度连续数组中最小的相等的值。
也就是说我们只需要先维护每个位置数值的最长出现距离,在维护每个距离中的最小值。就可以得到每个距离所能保证的最小值。
这里还有一段解释很好理解也放在这里
fx必须是长度k的所有段中的最小数,那么在输入数组中,在x的每次出现和它之前的出现之间,不应该有另一个长度>=k的段。例如,在{1,2,2,1,1}中,对于k=2和x=1,我们有一个长度为2的段{2,2},因此不是所有长度为2的段都有相同的“1”。注:我们必须考虑索引-1和n+1也等于选择的x(从开始和结束开始的段)我们可以通过为遍历数组的所有值维护一个以前的索引来计算这个值,并更新两个相同值之间的最大距离。然后我们可以排序,找到每k的最小值。
#include <bits/stdc++.h> using namespace std; int all[300005]; int last[300005]; int big[300005]; int ans[300005]; int main() { int T,N,i,con,t,ok; scanf("%d",&T); while(T--) { scanf("%d",&N); for(i=1;i<=N;i++) { last[i]=-1; big[i]=0; ans[i]=1e9; } for(i=0;i<N;i++) { scanf("%d",&all[i]); big[all[i]]=max(big[all[i]],i-last[all[i]]); last[all[i]]=i; }// big维护同一个点出现两次的最长距离。 con=1e9; for(i=1;i<=N;i++) { big[i]=max(big[i],N-last[i]); ans[big[i]]=min(ans[big[i]],i); }//ans维护每个最长距离的值的最小 for(i=1;i<=N;i++) { con=min(con,ans[i]); if(con>N) printf("-1 "); else printf("%d ",con); } printf("\n"); } return 0; }

浙公网安备 33010602011771号