Codeforces Round #673 (Div. 1)题解
作者:互联网
第一次做div1的Virtual participation,只写出来AB,自闭了
A. k-Amazing Numbers
题意:给定一个长为n的序列,每个元素为1~n
对于每个k=1~n,求最小的在所有长为k的子段中都出现的数
如果不存在,输出-1
题解:对于每个数求出最大的间隔,从小到大排序,更新答案即可
#include <bits/stdc++.h> using namespace std; int n, a[300011], las[300011], w, ans; struct D { int maxn, id; } b[300011]; bool cmp(D p1, D p2) { return p1.maxn < p2.maxn; } void solve() { memset(las, 0, sizeof(las)); memset(b, 0, sizeof(b)); scanf("%d", &n); ans = n+1; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) { b[a[i]].maxn = max(b[a[i]].maxn, i - las[a[i]]); las[a[i]] = i; } for(int i = 1; i <= n; i++) b[i].maxn = max(b[i].maxn, n + 1 - las[i]), b[i].id = i; sort(b+1, b+n+1, cmp); w = 0; for(int i = 1; i <= n; i++) { while(b[w+1].maxn <= i && w < n) ++ w, ans = min(ans, b[w].id); if(ans == n+1) printf("-1 "); else printf("%d ", ans); } printf("\n"); } int main() { int T; scanf("%d", &T); while(T--) solve(); return 0; }
B. Make Them Equal
题意:给定一个长为$n$的序列,你可以对它进行不大于$3n$次操作使得最终序列所有数相等:
选定整数$i,j,x(1<=i,j<=n,1<=x<=10^9)$,使$a[i]->a[i]-i*x,a[j]->a[j]+i*x$
操作时保证序列中所有数非负,无解输出$-1$
题解:注意到$a[i]$减的数与$a[j]$加的数相同,所以序列和不变
取平均值,若不为整数,则输出$-1$
因为$i=1$可以最细化每个数的变化,故考虑所有操作围绕$a[1]$进行
有一种方案为(以下$i∈[2,n]$):
1.将$a[i]$变为$i$的倍数
2.将$a[i]$变为$0$
对于每个$i$重复操作1,2(这两个操作可以使$a[1]+=a[i],a[i]=0$)
3.将$a[1]$的值平均分给每个$a[i]$
这样操作次数为$3(n-1)$,符合要求
考虑正确性:
对于1操作,因为$a[i]>=1$,所以在处理到第$i$个数时,$a[1]=sum[1,i-1]>=i-1$
又因为$a[i]%i<=i-1$,所以将$a[i]$变为$i$的倍数时,$a[1]$一定非负
其余操作的非负是很显然的
#include <bits/stdc++.h> using namespace std; int a[100011]; int n, sum; void solve() { scanf("%d", &n); sum = 0; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); sum += a[i]; } if(sum % n) { printf("-1\n"); return; } sum /= n; cout << 3 * (n-1) << endl; for(int i = 2; i <= n; i++) { int x = a[i] % i; cout << 1 << " " << i << " " << (i - x) % i << endl; a[1] -= (i - x) % i; a[i] += (i - x) % i; cout << i << " " << 1 << " " << a[i] / i << endl; a[1] += a[i]; a[i] = 0; } for(int i = 2; i <= n; i++) { cout << 1 << " " << i << " " << sum << endl; a[1] -= sum; a[i] += sum; } } int main() { int T; scanf("%d", &T); while(T--) solve(); return 0; }
标签:int,题解,sum,673,300011,序列,操作,Div 来源: https://www.cnblogs.com/huangxuanao/p/13966296.html