代码在最后

[HNOI2013]比赛

记忆化搜索

把每一位还需要多少分用\(27\)进制压进\(long\) \(long\),\(map\)记忆化一下即可

[HNOI2013]消毒

先考虑在二维平面

问题就是最小点覆盖

最小点覆盖 = 二分图最大匹配

对于每个点\((x,y)\),\(x\)连向\(y\)一条边,然后跑最大匹配

扩展到三维

好像不太好搞....

\(a*b*c<=5000\)

我们把\(a\)调换成\(min(a, b, c)\)

\(a\)最大为\(\sqrt[3]{5000}\)约\(17\)

对于每一层,要么和上面一起消,要么一次消掉这一层

枚举每层的状态

然后再跑最大匹配\(O(2^{17}n^3)\)

[HNOI2013]旅行

构造+单调队列

题目大意:给定\(1,-1\)组成的序列,分成\(m\)段,使得\(m\)段绝对值最大值最小

设:

后缀和为\(sum[i]\),后缀和为\(0\)的个数为\(cnt[i]\),序列和为\(S\)

然后分类讨论

  • \(S = 0\)

    \(1.\)若\(cnt[1] \ge m\),则\(ans = 0\).直接选\(0\)的位置即可

    维护一个单调队列

    \(2.\) 若\(cnt[1]<m\), 则\(ans = 1\)

    构造方法与 \(S \neq 0\) 一样

  • \(S \neq 0\)

    \(ans = \lceil\frac{|S|}{m}\rceil\)

    因为区间和为\(0\)的可以消掉,剩下的均分最小

    现在问题是如何求出字典序最小的方案

    假设上一个休息点已经确定为\(last\),当前决策到第\(i\)个休息点

    那么新的休息点(第i个休息点)$\(a\)需要满足:

    • \(n - a \ge m-i\)
    • \(\lceil \frac{|sum[a + 1]|}{m - i}\rceil \leq ans\)
    • \(|sum[last+1]-sum[a+1]| \leq ans\)

    好像不太好搞,考虑暴力

    我们可以对于每个每种\(sum\)开一个单调队列

    每次暴力从\([sum[last+1]-ans, sum[last+1]+ans]\) 取出合法的放进答案队列

    再维护答案队列的单调性,保证答案字典序最小

复杂度:\(O(m\lceil \frac{|S|}{m} \rceil) = O(|S|)\)

[HNOI2013]数列

\(20\%\):\(dp\)
\(f[i][j]\)前\(i\)位,已经分了\(j\)份
转移用前缀和优化一下
\(O(nk)\)

\(100\%\):

先写出式子:
设差分数组为:\(a_1, a_2, a_3, ..., a_{k-1}\)

\(\sum^{m}_{a_1 = 1}\sum^{m}_{a_2 = 1}\sum^{m}_{a_3 = 1}...\sum^{m}_{a_{k-1} = 1}(n-\sum_{i=1}^{k-1}a_i)\)
\(= n * m^{k-1} - \sum^{m}_{a_1 = 1}\sum^{m}_{a_2 = 1}\sum^{m}_{a_3 = 1}...\sum^{m}_{a_{k-1} = 1}\sum_{i=1}^{k-1}a_i\)
\(=n*m^{k-1}-\sum_{i=1}^{k-1}\sum_{a_i=1}^m*m^{k-2}\)
\(=n*m^{k-1}-(k-1)*m^{k-2}*\frac{(m+1)m}{2}\)

\(快速幂即可\)

  • 注意取模

[HNOI2013]游走

题面要求算边的期望

如果求出每条边期望经过次数,就可以求出答案

每条边经过次数,显然需要求出两端点期望经过次数

设点\(i\)期望次数为\(f[i]\)

\(deg[i]\)为\(i\)的入度

对于一个点\(i\)

存在边\(x-i\)

\(f[i] = \sum \frac{f[x]}{deg[x]}\)

\(f[1]\)要加\(1\),因为一开始在\(1\)

\(f[n]\)不要算,因为到了\(n\)就停止

这个东西列个方程,高斯消元求

然后算出每条边经过次数的期望
对于\(x-y\)
\(q[i] = f[x] / deg[x] + f[y] / deg[y]\)

显然经过次数多的边,赋值小

排序弄一下即可

[HNOI2013]切糕

最小割

题目其实就是求最小的代价使得每个纵轴被分成两部分

我们把每个点抽象成一条边,一个纵轴就是一条\(S−T\)的路径

但是题目要求\(|f(x,y)−f(x′,y′)|≤D\)
不能直接跑最小割

考虑如何限制

首先,\(|f(x,y)−f(x′,y′)|≤D\)是相互的
所以只要考虑 \(f(x,y)−f(x′,y′)≤D\)

那么对于\((x, y, z)\) 我们向它相邻列的第\(x-D\)层连一条\(inf\)边

贪心想一下,这样一定保证超过限制的两个点不会同时割掉

然后代码就很简单啦

Code

[HNOI2013]比赛

#include<bits/stdc++.h>#define LL unsigned long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}const int N = 15, Mod = 1e9 + 7;int n, s[N], ans, a[N], b[N], cnt1, cnt2;map<LL, LL> M;bool cmp(int x, int y) {return x > y;
}LL dfs(int x, int y) {if (a[x] + (n - y + 1) * 3 < s[x]) return 0;if (x == n) return 1;if (y > n) {for (int i = x + 1; i <= n; i++) b[i] = s[i] - a[i];sort(b + 1 + x, b + n + 1, cmp);LL S = n - x;for (int i = x + 1; i <= n; i++) S = S * 27 + b[i];if (M.find(S) != M.end()) return M[S];else return M[S] = dfs(x + 1, x + 2);}LL res = 0;if (a[x] + 3 <= s[x] && cnt1) {a[x] += 3;cnt1--;(res += dfs(x, y + 1)) %= Mod;a[x] -= 3;cnt1++;}if (a[x] < s[x] && a[y] < s[y] && cnt2) {a[x]++; a[y]++;cnt2--;(res += dfs(x, y + 1)) %= Mod;a[x]--; a[y]--;cnt2++;}if (a[y] + 3 <= s[y] && cnt1) {a[y] += 3;cnt1--;(res += dfs(x, y + 1)) %= Mod;a[y] -= 3;cnt1++;}return res;
}int main() {read(n);int sum;for (int i = 1; i <= n; i++)read(s[i]), sum += s[i];sort(s+1, s+1+n, cmp);cnt1 = sum - n * (n - 1);cnt2 = (sum - cnt1 * 3) / 2;printf("%lld\n", dfs(1, 2));return 0;
}

[HNOI2013]消毒

#include<bits/stdc++.h>#define LL long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}const int N = 5010;int a, b, c;int q[3][N], ql, ans;void init() {ql = 0;read(a), read(b), read(c);int mn = min(a, min(b, c));for (int i = 1; i <= a; i++)for (int j = 1; j <= b; j++)for (int k = 1; k <= c; k++) {int x; read(x);if (x == 1)q[0][++ql] = i, q[1][ql] = j, q[2][ql] = k;}if (mn == b) {swap(a, b); swap(q[0], q[1]);}else if (mn == c) {swap(a, c); swap(q[0], q[2]);}return ;
}bool flag[N], used[N];int match[N];struct node {int to, nxt;
}g[N];
int last[N], gl;void add(int x, int y) {g[++gl] = (node) {y, last[x]};last[x] = gl;
}bool dfs(int u) {for (int i = last[u]; i; i = g[i].nxt) {int v = g[i].to;if (used[v]) continue;used[v] = 1;if (!match[v] || dfs(match[v])) {match[v] = u;return 1;}}return 0;
}void work(int S) {int res = 0;for (int i = 0; i < a; i++)if (S & (1 << i))flag[i + 1] = 1, res++;else flag[i + 1] = 0;memset(last, 0, sizeof(last)); gl = 0;memset(match, 0, sizeof(match));for (int i = 1; i <= ql; i++)if (!flag[q[0][i]])add(q[1][i], q[2][i]);for (int i = 1; i <= b; i++) {for (int j = 1; j <= c; j++) used[j] = 0;if (dfs(i)) res++;}ans = min(ans, res);return ;
}int main() {int T;read(T);while (T--) {init();ans = 2147483647;for (int i = 0; i < (1 << a); i++)work(i);printf("%d\n", ans);}return 0;
}

[HNOI2013]旅行

#include<bits/stdc++.h>#define LL long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}
const int N = 5e5 + 5;
int n, m, a[N], sum[N], cnt[N];
struct Node { int l, r, v; } Line[N << 1]; int tot = 0;
struct deque { int head, tail, len;bool empty() { return !len; } int newNode(int l, int r, int v) { Line[++tot] = (Node){ l, r, v }; return tot; }int front() { return Line[head].v; } int back() { return Line[tail].v; } void pop_back() { tail = Line[tail].l, len--; } void pop_front() { head = Line[head].r, len--; } void push_back(int v) { if (!len)  head = tail = newNode(0, 0, v); else Line[tail].r = newNode(tail, 0, v), tail = Line[tail].r; len++; } void push(int v) { while (len && a[back()] > a[v]) pop_back(); push_back(v);}
} Q[N << 1], Qu[N << 1], *q = Q + N, *qu = Qu + N;#define min(x, y) ((a[x]) < (a[y]) ? (x) : (y))int main() {read(n), read(m);for (int i = 1; i <= n; i++)read(a[i]), read(sum[i]), sum[i] = sum[i] ? 1 : -1;for (int i = n - 1; i >= 1; i--) sum[i] += sum[i + 1];for (int i = n; i >= 1; i--) cnt[i] = cnt[i + 1] + (!sum[i]);int S = sum[1], d = S ? ceil(1.0 * abs(S) / m) : cnt[1] < m;cnt[n + 1] = -1;if (!d) {for (int i = 1, j = 2; i < m; i++) {while (cnt[j + 1] >= m - i) {if (!sum[j + 1]) q[0].push(j);j++;}printf("%d ", a[q[0].front()]);q[0].pop_front();}}else {for (int i = 2; i <= n; i++) qu[sum[i]].push_back(i - 1);int last = 0;a[n + 1] = n + 1;for (int i = 1; i < m; i++) {int ans = n + 1;for (int j = sum[last + 1] - d; j <= sum[last + 1] + d; j++) {if (ceil(1.0 * abs(j) / (m - i)) > d) continue;while (!qu[j].empty() && n - qu[j].front() >= m - i) {if (qu[j].front() > last) q[j].push(qu[j].front());qu[j].pop_front();}while (!q[j].empty() && q[j].front() <= last)q[j].pop_front();if (!q[j].empty()) ans = min(ans, q[j].front());}last = ans;printf("%d ", a[ans]);}}printf("%d\n", a[n]);return 0;
}

[HNOI2013]数列

#include<bits/stdc++.h>#define LL long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}LL n, k, m, p;LL fastpow(LL a, LL b) {LL res = 1;for (; b; b >>= 1, a = a * a % p) if (b & 1) res = res * a % p; return res;
}int main() {//freopen(".in", "r", stdin);//freopen(".out", "w", stdout);read(n), read(k), read(m), read(p);LL ans = (n % p * fastpow(m, k - 1) % p - (k - 1) * fastpow(m, k - 2) % p * ((m + 1) * m / 2 % p) % p  + p) % p;write(ans);return 0;
}

[HNOI2013]游走

#include<bits/stdc++.h>#define LL long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}const int N = 510;struct node {int to, nxt;
}g[N * 1000];
int last[N], gl, deg[N], n, m;
void add(int x, int y) {g[++gl] = (node) {y, last[x]};last[x] = gl;g[++gl] = (node) {x, last[y]};last[y] = gl;deg[y]++; deg[x]++;
}double a[N][N];void Gauss() {for (int i = 1, k; i < n; i++) {k = i;for (int j = i + 1; j < n; j++)if (fabs(a[k][i]) < fabs(a[j][i])) k = j;if (k != i) swap(a[k], a[i]);for (int j = i + 1; j < n; j++)for (int k = n; k >= i; k--)a[j][k] -= a[i][k] * a[j][i] / a[i][i];}for (int i = n - 1; i; i--) {for (int j = i + 1; j < n; j++)a[i][n] -= a[i][j] * a[j][n];a[i][n] /= a[i][i];}return ;
}double q[N * N];int X[N * N], Y[N * N];int main() {read(n); read(m);for (int i = 1, x, y; i <= m; i++) {read(x), read(y);add(x, y);X[i] = x, Y[i] = y;}   for (int x = 1; x < n; x++) {a[x][x] = 1;for (int i = last[x]; i; i = g[i].nxt) {int v = g[i].to;if (v == n) continue;a[x][v] = -1.0 / deg[v];}}a[1][n] = 1;Gauss();for (int i = 1; i <= m; i++)q[i] = a[X[i]][n] / deg[X[i]] + a[Y[i]][n] / deg[Y[i]];sort(q + 1, q + 1 + m);double ans = 0;for (int i = 1; i <= m; i++)ans += q[i] * (m - i + 1);printf("%.3lf\n", ans);return 0;
}

[HNOI2013]切糕

#include<bits/stdc++.h>#define LL long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}const int N = 80000, inf = 2147483647;struct node {int to, nxt, w;
}g[2000000];
int last[N], gl = 1;void add(int x, int y, int z) {g[++gl] = (node) {y, last[x], z};last[x] = gl;g[++gl] = (node) {x, last[y], 0};last[y] = gl;
}queue<int> q;
int dep[N], s, t, cur[N];bool bfs() {memset(dep, 0, sizeof(dep));dep[s] = 1;q.push(s);while (!q.empty()) {int u = q.front(); q.pop();for (int i = last[u]; i; i = g[i].nxt) {int v = g[i].to;if (!dep[v] && g[i].w) {dep[v] = dep[u]+1;q.push(v);}}}return dep[t] == 0 ? 0 : 1;
}int dfs(int u, int d) {if (u == t) return d;for (int &i = cur[u]; i; i = g[i].nxt) {int v = g[i].to;if (dep[v] == dep[u]+1 && g[i].w) {int di = dfs(v, min(d, g[i].w));if (di) {g[i].w -= di;g[i^1].w += di;return di;}}}return 0;
}int Dinic() {int ans = 0;while (bfs()) {for (int i = 1; i <= t; i++) cur[i] = last[i];while (int d = dfs(s, inf)) ans += d;}return ans;
}int a[50][50][50], id[50][50][50];int fx[] = {0, 1, -1, 0};
int fy[] = {1, 0, 0, -1};int main() {int p, q, r, d, tot = 0;read(p), read(q), read(r), read(d);for (int i = 1; i <= r; i++)for (int j = 1; j <= p; j++)for (int k = 1; k <= q; k++)read(a[i][j][k]), id[i][j][k] = ++tot;for (int j = 1; j <= p; j++)for (int k = 1; k <= q; k++)id[r+1][j][k] = ++tot;          s = tot+1, t = s+1;for (int i = 1; i <= p; i++)for (int j = 1; j <= q; j++)add(s, id[1][i][j], inf), add(id[r+1][i][j], t, inf);for (int k = 1; k <= r; k++)for (int i = 1; i <= p; i++)for (int j = 1; j <= q; j++)add(id[k][i][j], id[k+1][i][j], a[k][i][j]);for (int k = d+1; k <= r+1; k++)for (int i = 1; i <= p; i++)for (int j = 1; j <= q; j++) {for (int z = 0; z < 4; z++) {int x = i + fx[z], y = j + fy[z];if (x < 1 || y < 1 || x > p || y > q) continue;add(id[k][i][j], id[k-d][x][y], inf);}}printf("%d\n", Dinic());return 0;
}

转载于:https://www.cnblogs.com/zzy2005/p/10406638.html

[HNOI2013]题解相关推荐

  1. # HNOI2012 ~ HNOI2018 题解

    HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...

  2. [HNOI2013]数列(差分)

    [HNOI2013]数列 problem 洛谷链接 solution 假设每天的股价为 a[i]a[i]a[i].则需满足 ∀i<ka[i+1]−a[i]≤m\forall_{i<k}a[ ...

  3. [洛谷P3228] [HNOI2013]数列

    洛谷题目链接:[HNOI2013]数列 题目描述 小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨.股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N.在疯涨的K天中小T观察到: ...

  4. 【BZOJ3144】[Hnoi2013]切糕 最小割

    [BZOJ3144][Hnoi2013]切糕 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q ...

  5. 一句话题解(20170801~20170125)

    8.1 bzoj 4720 noip2016 换教室 floyd预处理+期望(薛定谔的猫) bzoj 4318 OSU! 三次函数期望值 从一次.二次推得 8.2 bzoj 1076 状压+期望DP ...

  6. [CQOI2009]循环赛[HNOI2013]比赛

    [CQOI2009]循环赛&&[HNOI2013]比赛--真是好题(差点没把我脑子烧坏-sd的无奈) 提前声明:感谢大佬看了他的题解后,我才恍然大悟 -好,先上题目 [CQOI2009 ...

  7. bzoj-3144 [Hnoi2013]切糕

    3144 [Hnoi2013]切糕 题目链接 题目大意 给出一个立方体(长宽高分别P,Q,R),按三维坐标每个点记作(x,y,z),点权为V(x,y,z),对于x,y位置从上到下有z层,但只能选择一层 ...

  8. [JS][dfs]题解 | #迷宫问题#

    题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...

  9. [JS][dp]题解 | #打家劫舍(一)#

    题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...

  10. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

最新文章

  1. python 连续输出日期_我想生成连续的日期
  2. linux下基于内存分析的rootkit检测方法
  3. 利用日志传送实现高可用性
  4. c语言文件的读写通讯录,学C三个月了,学了文件,用C语言写了个通讯录程序
  5. gzp解压命令 linux_Linux下最常用的压缩及解压缩命令
  6. 如果你被领导当众打了一耳光,你会怎么做?
  7. 计算机无法进行磁盘碎片整理,无法启动win7系统磁盘碎片整理的解决方案
  8. 鸡兔同笼的两种求解(C语言)
  9. linux安装ecshop,Linux安装ecshop
  10. webrtc rtt 计算
  11. idea 运行jmeter源码_IDEA 编译 Jmeter 4.0 ( 二次开发_1 )
  12. 在线高音测试软件,《在线测音高》使用说明
  13. ad20栅格_AD软件的3种栅格设置详解
  14. 2021-01-11小米随身wifi网络创建总是失败是什么问题?
  15. 友盟推送点击行为处理
  16. 服务器 系统打补丁,2019服务器系统打补丁方法
  17. 损失函数结果不理想解决方案——机器学习
  18. nyoj2 括号配对问题
  19. 目前智能手机 微型计算机,微型计算机基础知识1(新).ppt.ppt
  20. JavaScript — 基础语法

热门文章

  1. 船舶网络搭建项目案例
  2. 使用NodeJS调用Dubbo工程
  3. 03.学习笔记-Linux下根目录介绍
  4. UIButton的resizableImageWithCapInsets使用解析
  5. Client-Side UI Automation Provider - WinForm Sample
  6. ie下使用frameset布局导致跨域cookie丢失问题解决
  7. 为什么 Oracle 应该主推 NetBeans
  8. Net下的AppDomain编程 [摘录]
  9. ZooKeeper分布式过程协同技术详解2——了解ZooKeeper
  10. CXF处理Date类型的俩种方式