20161102测试总结

这次测试三道题都是贪心233…

T1

30分

暴力枚举每个排列,暴力算值。

100分

贪心,肯定先考虑一大一小地放,打个暴力对拍一下,可以发现答案为以下两种情况的最大值:

  • 最大的放中间,然后左边和右边依次放最小和次小的。
  • 最小的放中间,然后左边和右边依次放最大和次大的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <bits/stdc++.h>
using namespace std;
int a[110], t, n;
int f[110];
inline int solve() {
register int mid = (n >> 1) + 1, ans = 0;
f[mid] = a[n];
for (int i = mid - 1; i >= 1; i -= 2) f[i] = a[mid - i];
for (int i = mid - 2; i >= 1; i -= 2) f[i] = a[n - (mid - i - 1)];
for (int i = mid + 1; i <= n; i += 2) f[i] = a[i - mid + 1];
for (int i = mid + 2; i <= n; i += 2) f[i] = a[n - (i - mid)];
for (int i = 2; i <= n; i++) ans += abs(f[i] - f[i - 1]);
return ans;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> t;
for (int i = 1; i <= t; i++) {
cin >> n;
for (int j = 1; j <= n; j++) cin >> a[j];
sort(a + 1, a + n + 1);
int ans = solve();
reverse(a + 1, a + n + 1);
cout << "Case " << i << ": " << max(ans, solve()) << "\n";
}
return 0;
}

T2

100分

此题一看就是二分,然后考虑一下贪心,我们发现第一刀切在尽可能上面比较好,同理我们枚举当前刀的最后一行,在按列看列满不满足条件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 510;
const int iol = 1024 * 1024;
char buf[iol], *ioh, *iot, ioc;
bool iosig;
inline char read() {
if (ioh == iot) {
iot = (ioh = buf) + fread(buf, 1, iol, stdin);
if (ioh == iot) return -1;
}
return *ioh++;
}
template<class T>
inline bool read(T& x) {
iosig = false;
for (ioc = read(); !isdigit(ioc); ioc = read()) {
if (ioc == -1) return false;
if (ioc == '-') iosig = true;
}
x = 0;
while (ioc == '0') ioc = read();
for (; isdigit(ioc); ioc = read())
x = (x << 1) + (x << 3) + (ioc ^ '0');
ioh--;
if (iosig) x = -x;
return true;
}
int r, c, a, b;
int mp[MAXN][MAXN];
inline bool check(int mid) {
static int buf[MAXN], sum[MAXN];
memset(sum, 0, sizeof(sum));
int x = 0, y = 0, prei = 0, prej = 0;
for (int i = 1; i <= r; i++) {
y = prej = 0;
memset(buf, 0, sizeof(buf));
for (int j = 1; j <= c; j++)
buf[j] = buf[j - 1] + mp[i][j];
for (int j = 1; j <= c; j++)
sum[j] += buf[j];
for (int j = 1; j <= c; j++)
if (sum[j] - sum[prej] >= mid)
prej = j, y++;
if (y >= b)
prei = i, x++, memset(sum, 0, sizeof(sum));
}
return x >= a;
}
int main() {
read(r), read(c), read(a), read(b);
int range = 0;
for (int i = 1; i <= r; i++)
for (int j = 1; j <= c; j++)
read(mp[i][j]), range += mp[i][j];

int l = 0, r = range + 1;
while (l < r - 1) {
register int mid = l + r >> 1;
if (check(mid)) l = mid;
else r = mid;
}
cout << l;
return 0;
}

T3

玄学骗分65~75分

此算法来自qy和lcr神犇…
$ O(n ^{2}) $暴力,当n大于等于1000时,随机取点,rp算法,2333….

100分

SHY表示此题就是套路,然而此题确实是套路…
此题和scoi2016的美味很像,从高位往低位贪心,然后建成一颗trie树,再挂一个链,然后此题就解决了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <bits/stdc++.h>
using namespace std;
const int iol = 1024 * 1024;
char buf[iol], *ioh, *iot, ioc;
bool iosig;
inline char read() {
if (ioh == iot) {
iot = (ioh = buf) + fread(buf, 1, iol, stdin);
if (ioh == iot) return -1;
}
return *ioh++;
}
template<class T>
inline bool read(T& x) {
iosig = false;
for (ioc = read(); !isdigit(ioc); ioc = read()) {
if (ioc == -1) return false;
if (ioc == '-') iosig = true;
}
x = 0;
while (ioc == '0') ioc = read();
for (; isdigit(ioc); ioc = read())
x = (x << 1) + (x << 3) + (ioc ^ '0');
ioh--;
if (iosig) x = -x;
return true;
}
const int MAXN = 100010;
int n, tot;
int father[MAXN], son[MAXN * 20][2], pre[MAXN * 20], dis[MAXN];
struct Node {
int v, w;
Node() {}
Node(int v, int w) : v(v), w(w) {}
};
std::vector<Node> edge[MAXN];
inline void addEdge(int u, int v, int w) {
edge[u].push_back(Node(v, w));
edge[v].push_back(Node(u, w));
}
inline void bfs(int u = 1) {
queue<int> q;
q.push(u);
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = 0; i < edge[x].size(); i++) {
Node *now = &edge[x][i];
if (now->v != father[x]) {
father[now->v] = x;
dis[now->v] = dis[x] ^ now->w;
q.push(now->v);
}
}
}
}
int main() {
/*max{w}*/
int maxw = 0;
read(n);
for (int i = 0, u, v, w; i < n; i++)
read(u), read(v), read(w), addEdge(u, v, w), maxw = max(maxw, w);
bfs();
/*Math.log2(maxw)*/
int log = log2(maxw);
/*build*/
for (int i = 1, tmp; i <= n; i++) {
tmp = 0;
for (int j = log, x; j >= 0; j--) {
/*000000->_1_->000000*/
x = (dis[i] & (1 << j)) ? 1 : 0;
if (!son[tmp][x]) son[tmp][x] = ++tot;
tmp = son[tmp][x];
}
pre[tmp] = i;
}
int ans = 0;
/*digit calculate*/
for (int i = 1, tmp; i <= n; i++) {
tmp = 0;
for (int j = log, x; j >= 0; j--) {
x = (dis[i] & (1 << j)) ? 1 : 0;
if (son[tmp][!x]) tmp = son[tmp][!x];
else tmp = son[tmp][x];
}
ans = max(ans, dis[i] ^ dis[pre[tmp]]);
}
cout << ans;
return 0;
}

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×