其他分享
首页 > 其他分享> > Codeforces Round #673 (Div. 1)题解

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