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