inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
intmain(){ int T = read(); while (T --> 0) { int n = read(); int k = read(); int maxx = 0; std::priority_queue<int, std::vector<int>, std::greater<int> > q; for (int i = 1; i <= n; ++i) { int x = read(); q.push(x); maxx = std::max(maxx, x); } int ans = 0; while (maxx <= k) { int mn = q.top(); q.pop(); int tmn = q.top(); q.pop(); if (mn + tmn > k) break; ++ans; q.push(mn + tmn); q.push(mn); } printf("%d\n", ans); } return0; }
inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
constint MAXN = 1e5 + 10;
int n, ss; std::pair<int, int> less[MAXN]; int lcnt; std::pair<int, int> equal[MAXN]; int ecnt; std::pair<int, int> greater[MAXN]; int gcnt; int ans[MAXN];
intmain(){ int T = read(); while (T --> 0) { n = read(); ss = read(); lcnt = ecnt = gcnt = 0; for (int i = 1; i <= n; ++i) { int a = read(); if (2 * a < ss) less[++lcnt] = {a, i}; elseif (2 * a == ss) equal[++ecnt] = {a, i}; else greater[++gcnt] = {a, i}; } for (int i = 1; i <= lcnt; ++i) { ans[less[i].second] = 0; } for (int i = 1; i <= ecnt; ++i) { ans[equal[i].second] = i % 2; } for (int i = 1; i <= gcnt; ++i) { ans[greater[i].second] = 1; } for (int i = 1; i <= n; ++i) { printf("%d ", ans[i]); } puts(""); } return0; }
C. k-Amazing Numbers
题意简述
给定一个长为 的序列,定义一个 k-Amazing Number 为长度为 的所有区间中都出现的最小的数,没有就是 -1。对于每一个 ,求出 k-Amazing Number。
解题思路
考虑每个数对 k-Amazing Number 的影响。
注意到一个数成为 k-Amazing Number 的必要条件是它被所有长度为 k 的区间包含,也就是说,我们可以求出每个数被所有长为 k 的区间包含的最小的 k,它等于这个东西:
令 为这个数字出现的次数, 为这个数字出现的下标序列,,那么
因为这个 具有单调性,即如果 成立,那么 一定成立,所以知道了每个数被所有长 k 区间包含的最小的 ,就能很方便地求出每个 的 k-Amazing Number。
inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
constint MAXN = 3e5 + 10;
int n; int aa[MAXN]; int ind[MAXN]; int kmin[MAXN], mink[MAXN];
intmain(){ int t = read(); while (t --> 0) { n = read(); for (int i = 1; i <= n; ++i) { aa[i] = read(); mink[aa[i]] = std::max(mink[aa[i]], i - ind[aa[i]]); ind[aa[i]] = i; } for (int nw = 1; nw <= n; ++nw) { int mk = std::max(mink[nw], n - ind[nw] + 1); for (int j = mk; j <= n; ++j) { if (!kmin[j]) kmin[j] = nw; elsebreak; } } for (int i = 1; i <= n; ++i) { printf("%d ", !kmin[i] ? -1 : kmin[i]); kmin[i] = mink[i] = ind[i] = 0; } puts(""); } return0; }
inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
constint MAXN = 1e4 + 10;
structOperation { int i, j, x; Operation(int _i = 0, int _j = 0, int _x = 0) { i = _i; j = _j; x = _x; } } ops[MAXN * 3]; int cnt;
int n, aa[MAXN];
intmain(){ int T = read(); while (T --> 0) { int n = read(), sum = 0; for (int i = 1; i <= n; ++i) { aa[i] = read(); sum += aa[i]; } if (sum % n) { puts("-1"); continue; } for (int i = 2; i <= n; ++i) { // 把所有 i | a[i] 转移到 a[1] 里面 if (aa[i] % i == 0) { ops[++cnt] = Operation(i, 1, (aa[i] / i)); aa[1] += aa[i]; aa[i] = 0; } } for (int i = 2; i <= n; ++i) { if (aa[i]) { int need = i - aa[i] % i; ops[++cnt] = Operation(1, i, need); aa[i] += need; aa[1] -= need; ops[++cnt] = Operation(i, 1, (aa[i] / i)); aa[1] += aa[i]; aa[i] = 0; } } int send = sum / n; for (int i = 2; i <= n; ++i) { aa[i] += send; aa[1] -= send; ops[++cnt] = Operation(1, i, send); } printf("%d\n", cnt); for (int i = 1; i <= cnt; ++i) { printf("%d %d %d\n", ops[i].i, ops[i].j, ops[i].x); } cnt = 0; } return0; }
E. XOR Inverse
题意简述
给定一个长为 n 的序列,现在让你把它们都异或上一个数 x,使得新的序列逆序对最少。输出最少的逆序对数和此种情况下最小的 x。
inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
voidinsert(int x, int ind){ int u = 1; for (int i = 29; i >= 0; --i) { int now = ((x >> i) & 1); // printf("%d", now); int &next = node[u].next[now]; if (next == 0) next = ++cnt; node[u].dep = i; downs[u].push_back(ind); u = next; } node[u].dep = -1; // puts(""); downs[u].push_back(ind); }
voiddfs(int u = 1){ if (node[u].dep == -1) return; longlongint allinvpairs = 0, allpairs = 1ll * downs[node[u].next[0]].size() * downs[node[u].next[1]].size(); int siz = 0; for (auto v : downs[node[u].next[0]]) { while (siz < (int) downs[node[u].next[1]].size() && downs[node[u].next[1]][siz] < v) { ++siz; } allinvpairs += siz; } // printf("Node %d, dep %d, allpairs %d, allinvpairs %d.\n", u, node[u].dep, allpairs, allinvpairs); f[node[u].dep][0] += allinvpairs; f[node[u].dep][1] += allpairs - allinvpairs; dfs(node[u].next[0]); dfs(node[u].next[1]); }
intmain(){ n = read(); longlongint allinvs = 0, ans = 0; for (int i = 1; i <= n; ++i) { aa[i] = read(); insert(aa[i], i); } dfs(1); for (int i = 29; i >= 0; --i) { if (f[i][0] <= f[i][1]) { allinvs += f[i][0]; } else { allinvs += f[i][1]; ans |= (1ll << i); } } printf("%lld %lld\n", allinvs, ans); return0; }