Codeforces Round #673 Div. 2

A. Copy-paste

给定一串数组,可以选定两个数,将其中一个数加上另外一个数。每个数都不能超过个最大值K,问最多能进行几次这样的操作。

排序,其他都加上最小的数即可。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include<map>
#include<queue>
#include<sstream>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const ll mod = 998244353 ;
ll dataa[1000000 + 5];
int main(){
	ll n;
	cin >> n;
	while (n--)
	{
		ll m, k;
		ll ans = 0;
		cin >> m >> k;
		for (int i = 0; i < m; i++)scanf("%lld", &dataa[i]);
		sort(dataa, dataa + m);
		for (int i = 1; i < m; i++)ans += (k - dataa[i]) / dataa[0];
		cout << ans << '\n';
	}
}

B. Two Arrays

给定个值T,和一串数列,将其分为两部分,使每部分中一对数相加等于T的对数最小

排序,对于每个数x,二分T-x,标记上不同的颜色,x=T/2时,标记一半的x为黑,另一半为白。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include<map>
#include<queue>
#include<sstream>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const ll mod = 998244353;
P dataa[1000000 + 5];
int col[1000000 + 5] = {};
bool cmp(P a, P b) {
	return a.first < b.first;
}
int main() {
	ll n;
	cin >> n;
	while (n--)
	{
		ll m, k;
		ll ans = 0;
		cin >> m >> k;
		for (int i = 0; i < m; i++)scanf("%lld", &dataa[i].first), col[i] = -1, dataa[i].second = i;
		sort(dataa, dataa + m);
		for (int i = 0; i < m; i++) {
			if (col[dataa[i].second] == -1) {
				col[dataa[i].second] = 0;
				ll l = lower_bound(dataa + i + 1, dataa + m, P(k - dataa[i].first, 0), cmp) - dataa;
				if (l == m)continue;
				if (dataa[l].first != dataa[i].first)
					for (; dataa[l].first == k - dataa[i].first; l++)
						col[dataa[l].second] = 1;
				else {
					int tmp = 0;

					for (; dataa[l].first == k - dataa[i].first&&l<m; l++)
						col[dataa[l].second] = tmp ^ 1, tmp ^= 1;
				}
			}

		}
		for (int i = 0; i < m; i++)
			printf("%d ", col[i]);
		printf("\n");
	}
}

C. k-Amazing Numbers

定义K-number为在数组中任意长度都为K的区间内都出现的最小数,输出K等于1到n的K-number

维护每个数字在数组中出现的位置,从小到大寻找该数字对应的最小K。

可以知道,当一个数满足K-number,当K更大时这个数也能满足。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include<map>
#include<queue>
#include<sstream>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const ll mod = 998244353 ;
int dataa[1000000 + 5];
int datab[1000000 + 5];
int datac[1000000 + 5];
int ans[1000000 + 5] = {};
vector<int> e[300000 + 5];
bool cmp(P a, P b) {
	return a.first < b.first;
}
int main(){
	ll n;
	cin >> n;
	while (n--)
	{
		ll m;
		cin >> m;
		for (int i = 0; i < m; i++)scanf("%lld", &dataa[i]),ans[i]=-1,datab[i]=dataa[i],e[i]=vector<int>(),e[i].push_back(-1);
		ans[m] = -1;
		sort(dataa, dataa + m);
		//sort(datac, datac + m);
		ll len = unique(dataa, dataa + m) - dataa;
		for (int i = 0; i < m; i++)datab[i] =lower_bound(dataa,dataa+len,datab[i])-dataa,e[datab[i]].push_back(i);
		for (int i = 0; i < len; i++) {
			ll max1 = e[i][0];
			e[i].push_back(m);
		
			for (int j = e[i].size() - 1; j > 0; j--)e[i][j] = e[i][j] - e[i][j - 1],max1=max(max1,(ll)(e[i][j]));
			if (ans[max1] == -1)ans[max1] = dataa[i];
		}
		for (int i = 1; i <=m; i++) {
			if (i != 1 && (ans[i] == -1||(ans[i]>ans[i-1]&&ans[i-1]!=-1)))ans[i] = ans[i - 1];
			printf("%d ", ans[i]);
		}
		printf("\n");
	}
}

D. Make Them Equal

给定一个数列,可以进行以下操作:

选定i,j,x

ai=ai-x*i,aj=aj+x*i

在3n次内令数列全部相同

当我们把所有数都加到a1上,我们就能随意分配数字

我们可以先把a1的一部分转移到ai上,令ai%i==0,再把ai全部转哟到a1.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include<map>
#include<queue>
#include<sstream>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const ll mod = 998244353;
int dataa[1000000 + 5];
int ans[1000000 + 5][3] = {};
bool cmp(P a, P b) {
	return a.first < b.first;
}
int main() {
	ll n;
	cin >> n;
	while (n--)
	{
		ll cnt = 0;
		ll m;
		cin >> m;
		dataa[0] = 0;
		for (int i = 1; i <= m; i++) {
			scanf("%d", &dataa[i]);
			dataa[0] += dataa[i];
		}
		if ((dataa[0] % m)) {
			printf("-1\n");
			continue;
		}
		for (int i = 2; i <= m; i++) {
			if (dataa[i] % i == 0) {
				ans[cnt][0] = i;
				ans[cnt][1] = 1;
				ans[cnt++][2] = dataa[i] / i;
			}
			else {
				ans[cnt][0] = 1;
				ans[cnt][1] = i;
				ans[cnt++][2] = i - dataa[i] % i;
				ans[cnt][0] = i;
				ans[cnt][1] = 1;
				ans[cnt++][2] = (dataa[i]+i-1) / i;
			}
		}
		for (int i = 2; i <= m; i++) {
			ans[cnt][0] = 1;
			ans[cnt][1] = i;
			ans[cnt++][2] = dataa[0]/m;
		}
		printf("%d\n", cnt);
		for (int i = 0; i <cnt; i++)printf("%d %d %d\n", ans[i][0], ans[i][1], ans[i][2]);
	}
}

E. XOR Inverse

给定数组,找到个数x,用数组每个数异或x,新数组中逆序对最少

先用字典树维护数组中的二进制数,并且每个节点中存着该节点的编号。从高到低位贪心选取逆序对小的(0或1)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include<map>
#include<queue>
#include<sstream>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
ll trie[5000000][2];
ll tot = 0;
ll ans[40][2] = {};
vector<int> e[5000000];
void ins(int k, int pos) {
	ll p = 0,c;
	for (int i = 30; i >= 0; i--) {
		c = (k>>i) & 1;
		if (trie[p][c] == 0)trie[p][c] = ++tot;
		p = trie[p][c];
		e[p].push_back(pos);
	}
}
void dfs(int k, int pos) {
	//if (pos == -1)return;
	ll l = trie[k][0], r = trie[k][1];
	if (l)dfs(l, pos - 1);
	if (r)dfs(r, pos - 1);
	if (!trie[k][0] || !trie[k][1])return;
	
	ll tmp = 0, ans1 = 0;
	for (int i = 0; i < e[l].size(); i++) {
		while (tmp < e[r].size() && e[r][tmp] < e[l][i])tmp++;
		ans1 += tmp;
	}
	ans[pos][0] += ans1;
	ans[pos][1] += (ll)e[l].size() * e[r].size() - ans1;
}
int main() {
	ll n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int tmp;
		scanf("%d", &tmp);
		ins(tmp, i);
	}
	dfs(0, 30);
	ll res=0, x=0;
	for (int i =0; i <= 30; i++) {
		if (ans[i][0] <= ans[i][1])
			res += ans[i][0];
		else {
			res += ans[i][1];
			x += (1 << i);
		}
	}
	cout << res << ' ' << x;
}
posted @ 2020-10-11 22:06  PopHirasawa  阅读(115)  评论(0编辑  收藏  举报