「USACO2011 11月ゴールド」問題解決レポート
中央値以上T1、
\(説明\) :
所定の長さ\(N \(N当量\ 10 ^ 5)\) シーケンス\(\ {A_N \} \(a_iを\のLeq 10 ^ 9)\) 、中央値Q以上(K \)\間隔の数。(間隔は偶数がある場合に、中央値は1つの大きい方として定義されます)
\(溶液\) :
場合\(a_iを\ GEQ K \)標識位置\(1 \)、\ (a_iを<K \)は、標識された\(0 \)と呼ばれ、このシーケンス\(B \)、配列プレフィックスそして、と呼ばれる\(前\) ;
間隔\([L、R&LT] \) :ときに限り質問の意味を満たす
\ [1 ' - (1 - 1 )\当量2 \回(pre_r - pre_ {1 - 1 })\]
同じ変数の吐出側:
。\ [R&LT - 2 \タイムズpre_r \のLeq(L - 1) - 2 \ L回pre_ { - } 1 \]
右端をENUM、左メンテナンスが容易なデータ構造を見つけます。条件を満たすように、左いくつかのポイントがあります。
\(出典\) :
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
const int N = 1e5 + 5;
int n, nn, k, a[N], pre[N];
long long res;
struct binary_index_tree {
int a[N << 1];
void insert(int p) { for (; p <= nn; p += (p & -p)) ++a[p]; }
int ask(int p) { int ret = 0; for (; p; p -= (p & -p)) ret += a[p]; return ret; }
} bit;
int main() {
//freopen("in", "r", stdin);
n = in(), k = in(), nn = n + n;
for (int i = 1; i <= n; ++i)
a[i] = in();
for (int i = 1; i <= n; ++i)
pre[i] = pre[i - 1] + (a[i] >= k);
bit.insert(n);
for (int i = 1; i <= n; ++i) {
res += bit.ask(pre[i] + pre[i] - i + n);
bit.insert(pre[i] + pre[i] - i + n);
}
printf("%lld\n", res);
return 0;
}
T2、バイナリ数独
\(説明\) :
与え\を(9 \回9 \)\(01 \)行列、いくつかの最小数のQを変更することができ、各行及び各ブロックの各列との排他的論理和(\ 0 \) 。
\(溶液\) :
\(F_ {K、I、 X、Y、Zは} \) セクションを表し\(K \)行、\(1 \)をする(K \)\各列状態XORのとするためのラインI(\を\)(2進数)、現在の三グリッドがXORである\(X、Y、Z \ ) 操作の最小数、
一次転写列挙\(K \)動作線、
各ブロックのメモ最後の行の\(X、Y、Zの\ ) である\(0 \) 。
\(出典\) :
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
int a[11][4], b[515][4], f[11][515][2][2][2];
char str[15];
int main() {
//freopen("in", "r", stdin);
for (int i = 1; i <= 9; ++i) {
scanf(" %s", str + 1);
for (int j = 1; j <= 9; ++j)
a[i][0] = (a[i][0] << 1) | (str[j] == '1');
for (int j = 0; j < 9; ++j)
a[i][j / 3 + 1] ^= (a[i][0] >> j) & 1;
}
for (int i = 1; i < 512; ++i) {
b[i][0] = b[i - (i & -i)][0] + 1;
for (int j = 0; j < 9; ++j)
b[i][j / 3 + 1] ^= (i >> j) & 1;
}
memset(f, 0x3f, sizeof(f));
f[0][0][0][0][0] = 0;
for (int k = 1, tmp, t1, t2, t3; k <= 9; ++k) {
if (k % 3 == 0) {
for (int i = 0; i < 512; ++i)
for (int j = 0; j < 512; ++j) {
if (b[j ^ a[k][0]][0] & 1)
continue;
t1 = a[k][1] ^ b[j][1];
t2 = a[k][2] ^ b[j][2];
t3 = a[k][3] ^ b[j][3];
tmp = f[k - 1][i ^ j ^ a[k][0]][t1][t2][t3];
chk_min(f[k][i][0][0][0], tmp + b[j][0]);
}
} else {
for (int i = 0; i < 512; ++i)
for (int x = 0; x < 2; ++x)
for (int y = 0; y < 2; ++y)
for (int z = 0; z < 2; ++z)
for (int j = 0; j < 512; ++j) {
if (b[j ^ a[k][0]][0] & 1)
continue;
t1 = x ^ a[k][1] ^ b[j][1];
t2 = y ^ a[k][2] ^ b[j][2];
t3 = z ^ a[k][3] ^ b[j][3];
tmp = f[k - 1][i ^ j ^ a[k][0]][t1][t2][t3];
chk_min(f[k][i][x][y][z], tmp + b[j][0]);
}
}
}
printf("%d\n", f[9][0][0][0][0]);
return 0;
}
T3、牛障害物競走
\(説明\) :
所与\(N \(n個の\当量 250)\) 軸に平行な線分は、線分を極力選択されるように二十から二ない交点(頂点も考慮)、及び水平横、縦及び垂直これらのセグメント線分の間に交点が存在しないことを保証するために、ラインセグメントの最大数の出力を選出することができます。
より大きいコーディネート\(0 \)以上、およびない\(10 ^ 9 \) 。
\(溶液\) :
図半値独立したセット。
\(出典\) :
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
const int N = 255;
struct segment {
int x1, y1, x2, y2;
} a[N], b[N];
int n, x, y, mp[N][N], mat[N];
void prep() {
for (int i = 1; i <= x; ++i)
if (a[i].x1 > a[i].x2)
std::swap(a[i].x1, a[i].x2);
for (int i = 1; i <= y; ++i)
if (b[i].y1 > b[i].y2)
std::swap(b[i].y1, b[i].y2);
for (int i = 1; i <= x; ++i) {
for (int j = 1; j <= y; ++j) {
if (b[j].y1 <= a[i].y1 && a[i].y2 <= b[j].y2 &&
a[i].x1 <= b[j].x1 && b[j].x2 <= a[i].x2)
mp[i][j] = 1;
}
}
}
int vis[N];
int dfs(const int u, const int tim) {
if (vis[u] == tim)
return 0;
vis[u] = tim;
for (int v = 1; v <= y; ++v) {
if (!mp[u][v])
continue;
if (!mat[v] || dfs(mat[v], tim)) {
mat[v] = u;
return 1;
}
}
return 0;
}
int hungary() {
int ret = 0;
for (int i = 1; i <= x; ++i)
ret += dfs(i, i);
return ret;
}
int main() {
//freopen("in", "r", stdin);
n = in();
for (int i = 1; i <= n; ++i) {
a[++x] = (segment){in(), in(), in(), in()};
if (a[x].x1 == a[x].x2)
b[++y] = a[x--];
}
prep();
printf("%d\n", n - hungary());
return 0;
}