您的位置:首页 > 其它

[比赛][ZJOI2011 day1]

2017-03-13 15:16 465 查看

[比赛][ZJOI2011 day1]

pre():

只是用ZJOI2011的day1来考了一场省选模拟赛。。然而在这之前并没有做过。。

实际比赛:

T1

T1推了一下发现是一个Dp+单调栈?不过要分成三面做。。。于是打了半个小时调了一个小时,因为为了把三面中的某一面作为底面打了翻转操作,调了好久。。。

A掉了

T2

好神的数学题啊并不会,隐隐约约感觉是结论题。。

哇N,K<=10感觉可以打暴力,打完发现复杂度是NK根本过不了。。。于是改成了打表。。但是打错了QAQ

爆0了

T3

好神的图论啊并不会,隐隐约约感觉是最小割(题目就是最小割啊)。。

哇N<=50感觉可以打暴力,于是对每两对点跑了一遍最小割就过了样例(样例怎么一条边都没有),啊呀自己造了一组数据跑过了就不管了。

拿了暴力30分

总分130啊好数字

题解:

T1

用f[i][j][k]表示第k层以(i,j)为右下角的最大的正方形大小,g[i][j][k]表示当前位置是否完好,那么:

f[i][j][k]=(Min(f[i−1][j][k],f[i][j−1][k],f[i−1][j−1][k])+1)∗g[i][j][k]

再枚举每个左下角(i,j),不妨设f[i][j][k]为c[k],那么对于c[k]的一段区间,它的长宽肯定只能取这段区间里的最小值,所以用单调栈分别维护c[k]最小能向左右到l[k],r[k],这样最大值就是:

ans=Max(c[k]∗(r[k]−l[k]+1))

注意要翻转两次,对每个面各做一次

[b]代码:[/b]

#include <bits/stdc++.h>
using namespace std;
const int Maxn = 155;
int P, Q, R, g[Maxn][Maxn][Maxn], f[Maxn][Maxn][Maxn], ans, tmp[Maxn][Maxn][Maxn];
inline int Min(const int &a, const int &b) {
return a < b ? a : b;
}
inline int Max(const int &a, const int &b) {
return a > b ? a : b;
}
int c[Maxn], l[Maxn], r[Maxn], top, st[Maxn];
inline int calc(const int &n) {
c[0] = c[n + 1] = -1;
top = 0;
for (int i = 1; i <= n; i++) {
while (top && c[i] <= c[st[top]]) top--;
l[i] = st[top] + 1; st[++top] = i;
}
top = 0; st[++top] = n + 1;
for (int i = n; i; i--) {
while (top && c[i] <= c[st[top]]) top--;
r[i] = st[top] - 1; st[++top] = i;
}
for (int i = 1; i <= n; i++) ans = Max(ans, (r[i] - l[i] + 1) * c[i]);

}
inline void circle1(void) {
for (int i = 1; i <= P; i++)
for (int j = 1; j <= Q; j++)
for (int k = 1; k <= R; k++) g[i][R - k + 1][j] = tmp[i][j][k];
swap(Q, R);
}
inline void circle2(void) {
swap(Q, R);
for (int i = 1; i <= P; i++)
for (int j = 1; j <= Q; j++)
for (int k = 1; k <= R; k++) g[k][j][P - i + 1] = tmp[i][j][k];
swap(P, R);
}
inline void solve(void) {
for (int k = 1; k <= R; k++)
for (int i = 1; i <= P; i++)
for (int j = 1; j <= Q; j++) {
if (g[i][j][k]) f[i][j][k] = Min(f[i - 1][j - 1][k],
Min(f[i - 1][j][k], f[i][j - 1][k])) + 1;
else f[i][j][k] = 0;
}
for (int i = 1; i <= P; i++)
for (int j = 1; j <= Q; j++) {
memset(c, 0, sizeof c);
for (int k = 1; k <= R; k++)
c[k] = f[i][j][k];
calc(R);
}

}
int main(void) {
//freopen("monument.in", "r", stdin);
//freopen("monument.out", "w", stdout);

scanf("%d%d%d\n", &P, &Q, &R);
for (int j = 1; j <= Q; j++)
for (int i = 1; i <= P; i++) {
for (int k = 1; k <= R; k++) tmp[i][j][k] = g[i][j][k] = (getchar() == 'N' ? 1 : 0);
getchar();
}
solve(); circle1(); solve(); circle2(); solve();
printf("%d\n", ans << 2);
fclose(stdin), fclose(stdout);
return 0;
}


T2

结论题吧,结论我不会证,答案是:

K+1N−1∗(N−K+1)KN

[b]代码:[/b]

import math
import sys
import io
def gcd(a, b):
if a < b:
a, b = b, a

while b != 0:
temp = a % b
a = b
b = temp

return a

t=int(input(''))
i = 1
while (i <= t):
n, k = map(int,sys.stdin.readline().split())
if n > k :
print ("0 1")
else :
ans1 = math.pow((k + 1),(n - 1)) * (n - k + 1)
ans2 = math.pow(k,n)
g = gcd(ans1, ans2)
ans1 = int(ans1 / g)
ans2 = int(ans2 / g)
print (ans1, ans2)

i = i + 1


T3

fhq神犇题解:

首先,注意这样一个事实:如果(X,Y)是某个s1-t1最小割,(Z,W)是某个s2-t2最小割,那么X∩Z、X∩W、Y∩Z、Y∩W这四项不可能均非空。也就是说,最小割不可能相互跨立。

这个蕴含了,最多一共有N-1个不同的s-t最小割。只需把这些割找出来即可。

寻找的方法:首先,在V中任意找两个点a,b,求最大流,把V划分为割X-Y,之后对X、Y分别递归地进行划分。这样就能得到N-1个割了。

[b]代码:[/b]

#include <bits/stdc++.h>
using namespace std;
const int Maxn = 200;
const int INF = 0x3f3f3f3f;
inline int Min(const int &a, const int &b) {
return a < b ? a : b;
}
inline int Max(const int &a, const int &b) {
return a > b ? a : b;
}
namespace IO {
inline char get(void) {
static char buf[1000000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
inline void read(int &x) {
x = 0; static char c; bool f = 0;
for (; !(c >= '0' && c <= '9'); c = get()) if (c == '-') f = 1;
for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get()); if (f) x = -x;
}
inline void read(char &x) {
x = get();
while (!(x >= 'A' && x <= 'Z')) x = get();
}
inline void write(int x) {
if (!x) return (void)puts("0");
if (x < 0) putchar('-'), x = -x;
static short s[12], t;
while (x) s[++t] = x % 10, x /= 10;
while (t) putchar('0' + s[t--]);
putchar('\n');
}
};
int head[Maxn], sub;
struct Edge {
int to, nxt, v;
Edge(void) {}
Edge(const int &to, const int &nxt, const int &v) : to(to), nxt(nxt), v(v) {}
} edge[100005];
inline void add(int a, int b, int v) {
edge[++sub] = Edge(b, head[a], v), head[a] = sub;
}
inline void restore(void) {
for (int i = 2; i <= sub; i += 2)
edge[i].v = edge[i ^ 1].v = (edge[i].v + edge[i ^ 1].v) >> 1;
}
int T, Q, n, m, ans[Maxn][Maxn], tmp[Maxn], a[Maxn], h[Maxn];
bool mark[Maxn];
inline bool bfs(int S, int T) {
memset(h, -1, sizeof h);
queue<int> qu;
h[S] = 0; qu.push(S);
while (!qu.empty()) {
int u = qu.front(); qu.pop();
for (int i = head[u], v; i; i = edge[i].nxt) {
v = edge[i].to;
if (h[v] == -1 && edge[i].v) h[v] = h[u] + 1, qu.push(v);
}
}
return h[T] != -1;
}
inline int dfs(int T, int u, int flow) {
if (u == T) return flow;
int w, used = 0;
for (int i = head[u], v; i; i = edge[i].nxt) {
v = edge[i].to;
if (h[v] != h[u] + 1) continue;
w = dfs(T, v, Min(edge[i].v, flow - used));
edge[i].v -= w; edge[i ^ 1].v += w;
used += w;
if (used == flow) return flow;
}
if (!used) h[u] = -1;
return used;
}
inline void dfs(int x) {
mark[x] = 1;
for (int i = head[x], v; i; i = edge[i].nxt) {
v = edge[i].to;
if (edge[i].v && !mark[v]) dfs(v);
}
}
inline void solve(int l, int r) {
if (l == r) return ; restore();
int S = a[l], T = a[r], t = 0;
while (bfs(S, T)) t += dfs(T, S, INF);
memset(mark, 0, sizeof mark);
dfs(S);
for (int i = 1; i <= n; i++)
if (mark[i]) for (int j = 1; j <= n; j++)
if (!mark[j]) ans[i][j] = ans[j][i] = Min(ans[i][j], t);
int L = l, R = r;
for (int i = l; i <= r; i++) {
if (mark[a[i]]) tmp[L++] = a[i];
else tmp[R--] = a[i];
}
for (int i = l; i <= r; i++) a[i] = tmp[i];
solve(l, L - 1); solve(R + 1, r);
}
int main(void) {
//freopen("in.txt", "r", stdin);
IO::read(T);
while (T--) {
memset(head, 0, sizeof head);
memset(ans, 0x3f, sizeof ans);
sub = 1;
IO::read(n), IO::read(m);
for (int i = 1, u, v, w; i <= m; i++) {
IO::read(u), IO::read(v), IO::read(w);
add(u, v, w), add(v, u, w);
}
for (int i = 1; i <= n; i++) a[i] = i;
solve(1, n);
IO::read(Q);
while (Q--) {
int tans = 0, x;
IO::read(x);

for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (ans[i][j] <= x) tans++;
IO::write(tans);
}
putchar('\n');
}
return 0;
}


撒花~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  zjoi bzoj