2.4 加工并存储数据的数据结构
优先队列
POJ 3614 C个cow各需要一定范围的SPF防晒霜,给出L种防晒霜及其数量,求最大能满足多少cow的需要
按右端点排序,优先使用SPF小的防晒霜

1 #include <algorithm>
2 #include <iostream>
3 #include <queue>
4 using namespace std;
5 #define P pair<int, int>
6
7 int num[1005];
8
9 int main() {
10 ios::sync_with_stdio(false);
11 int c, l, x, y;
12 cin >> c >> l;
13 priority_queue<P, vector<P>, greater<P> > que;
14 for (int i = 0; i < c; i++) {
15 cin >> x >> y;
16 que.push(P(y, x));
17 }
18 for (int i = 0; i < l; i++) {
19 cin >> x >> y;
20 num[x] += y;
21 }
22 int r = 0;
23 while (!que.empty()) {
24 int a = que.top().second, b = que.top().first;
25 for (int i = a; i <= b; i++) {
26 if (num[i]) {
27 num[i]--;
28 r++;
29 break;
30 }
31 }
32 que.pop();
33 }
34 cout << r;
35 }
POJ 2010 C个元素(具有分数和代价),选取N(奇数)个,使得代价不超过F且分数的中位数尽可能大
枚举中位数,从前一部分和后一部分分别选出代价最小的(N-1)个。而相邻中位数这一信息是可以log N转移的

1 #include <algorithm>
2 #include <cstdio>
3 #include <iostream>
4 #include <queue>
5 #include <set>
6 #include <vector>
7 #include <cstdlib>
8 using namespace std;
9 #define ll long long
10 #define pii pair<int, int>
11 #define fi first
12 #define se second
13 #define pb push_back
14
15 const int maxn = 1e5 + 5;
16
17 int n, c, f, pos1, pos2;
18 ll tmp;
19
20 struct node {
21 int sc, val;
22 bool operator<(const node &o) const { return sc > o.sc; }
23 } a[maxn];
24
25 priority_queue<int> pque1;
26 priority_queue<int, vector<int>, greater<int> > pque2;
27
28 ll tot[maxn];
29
30 int main() {
31 scanf("%d %d %d", &n, &c, &f);
32 for (int i = 0; i < c; i++) {
33 scanf("%d %d", &a[i].sc, &a[i].val);
34 }
35 sort(a, a + c);
36 pos1 = n / 2, pos2 = c - pos1 - 1;
37 for (int i = pos1; i <= pos2; i++) tot[i] = a[i].val;
38 for (int i = 0; i < pos1; i++) {
39 tmp += a[i].val;
40 pque1.push(a[i].val);
41 }
42 tot[pos1] += tmp;
43 for (int i = pos1 + 1; i <= pos2; i++) {
44 pque2.push(a[i - 1].val);
45
46 tmp -= pque1.top();
47 pque2.push(pque1.top());
48 pque1.pop();
49
50 tmp += pque2.top();
51 pque1.push(pque2.top());
52 pque2.pop();
53
54 tot[i] += tmp;
55 }
56 while (!pque1.empty()) pque1.pop();
57 while (!pque2.empty()) pque2.pop();
58 tmp = 0;
59 for (int i = pos2 + 1; i < c; i++) {
60 tmp += a[i].val;
61 pque1.push(a[i].val);
62 }
63 tot[pos2] += tmp;
64 for (int i = pos2 - 1; i >= pos1; i--) {
65 pque2.push(a[i + 1].val);
66
67 tmp -= pque1.top();
68 pque2.push(pque1.top());
69 pque1.pop();
70
71 tmp += pque2.top();
72 pque1.push(pque2.top());
73 pque2.pop();
74
75 tot[i] += tmp;
76 }
77
78 for (int i = pos1; i <= pos2; i++) {
79 if (tot[i] <= f) {
80 printf("%d\n", a[i].sc);
81 exit(0);
82 }
83 }
84 printf("-1\n");
85 }
并查集
POJ 2236 N个节点,对某一节点操作可以修复该节点,已修复节点之间的距离在d以内时是可联系的,联系具有传递性;查询两个节点能否联系
修复一个节点时,遍历其他其它节点,如果在距离以内且已修复就用并查集并在一起

1 #include <cmath>
2 #include <iostream>
3 using namespace std;
4 #define P pair<int, int>
5
6 const double eps = 1e-8;
7
8 P point[1001];
9 int vis[1001], par[1001], ran[1001];
10
11 void init(int x) {
12 for (int i = 1; i <= x; i++) {
13 par[i] = i;
14 }
15 }
16
17 int find(int x) {
18 if (x == par[x]) return x;
19 return par[x] = find(par[x]);
20 }
21
22 void unite(int x, int y) {
23 x = find(x);
24 y = find(y);
25 if (x == y) return;
26 if (ran[x] < ran[y])
27 par[x] = y;
28 else {
29 par[y] = x;
30 if (ran[x] == ran[y]) ran[x]++;
31 }
32 }
33
34 bool same(int x, int y) { return find(x) == find(y); }
35
36 int main() {
37 ios::sync_with_stdio(false);
38 int d, n, x, y;
39 cin >> n >> d;
40 init(n);
41 for (int i = 1; i <= n; i++) {
42 cin >> point[i].first >> point[i].second;
43 }
44 char c;
45 while (cin >> c) {
46 if (c == 'O') {
47 cin >> x;
48 if (vis[x] == 1) continue;
49 vis[x] = 1;
50 int xi = point[x].first, yi = point[x].second;
51 for (int i = 1; i <= n; i++) {
52 if (vis[i] &&
53 (xi - point[i].first) * (xi - point[i].first) +
54 (yi - point[i].second) * (yi - point[i].second) <=
55 d * d) {
56 unite(x, i);
57 }
58 }
59 } else {
60 cin >> x >> y;
61 if (same(x, y))
62 cout << "SUCCESS\n";
63 else
64 cout << "FAIL\n";
65 }
66 }
67 }
POJ 1703 N个人,给出M条信息,可以确认其中两人是否是同一阵营;查询两个人是否是同一阵营
弱化版的食物链

1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 using namespace std;
5
6 int par[200001], ran[200001];
7
8 void init(int x) {
9 for (int i = 1; i <= x; i++) {
10 par[i] = i;
11 ran[i] = 0;
12 }
13 }
14
15 int find(int x) {
16 if (x == par[x]) return x;
17 return par[x] = find(par[x]);
18 }
19
20 void unite(int x, int y) {
21 x = find(x);
22 y = find(y);
23 if (x == y) return;
24 if (ran[x] < ran[y])
25 par[x] = y;
26 else {
27 par[y] = x;
28 if (ran[x] == ran[y]) ran[x]++;
29 }
30 }
31
32 bool same(int x, int y) { return find(x) == find(y); }
33
34 int main() {
35 ios::sync_with_stdio(false);
36 int t, n, m, x, y;
37 char ch[2];
38 scanf("%d", &t);
39 while (t--) {
40 scanf("%d%d", &n, &m);
41 init(2 * n);
42 while (m--) {
43 scanf("%s%d%d", ch, &x, &y);
44 if (ch[0] == 'D') {
45 unite(x, y + n);
46 unite(x + n, y);
47 } else {
48 if (same(x, y))
49 cout << "In the same gang.\n";
50 else if (same(x, y + n))
51 cout << "In different gangs.\n";
52 else
53 cout << "Not sure yet.\n";
54 }
55 }
56 }
57 }
AOJ 2170 一棵树,给某一点打标记,查询一个节点最近的打过标记的祖先
打标记时,把双亲节点改为自身,查询时往上走。最坏时间复杂度是O(N^2),没有T,大概率是数据问题

1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int par[100005];
5
6 int main() {
7 ios::sync_with_stdio(false);
8 int n, q, x;
9 char s[2];
10 par[1] = 1;
11 while (scanf("%d%d", &n, &q) != EOF) {
12 if (n == 0 && q == 0) break;
13 for (int i = 2; i <= n; i++) scanf("%d", &par[i]);
14 long long sum = 0;
15 for (int i = 0; i < q; i++) {
16 scanf("%s%d", s, &x);
17 if (s[0] == 'Q') {
18 while (x != par[x]) x = par[x];
19 sum += x;
20 } else {
21 par[x] = x;
22 }
23 }
24 cout << sum << "\n";
25 }
26 }
END
来源:https://www.cnblogs.com/hs-zlq/p/12210604.html
