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 << '
';
}
}
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("
");
}
}
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("
");
}
}
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
");
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
", cnt);
for (int i = 0; i <cnt; i++)printf("%d %d %d
", 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;
}