-
3367 Expressions (3)
-
2274 The Race (6)
-
3321 Apple Tree (6)
-
1177 Picture (7, challenge problem)
-
1195 Mobile phones (8, challenge problem)
-
2750 Potted Flower (9, challenge problem)
poj1330
最近公共祖先的Tarjan离线算法
#include<cstdio> #include<cstring> #include<vector> #include<iostream> #include<iterator> using namespace std; int n, a, b; int fa[10010]; vector <int> adj[10010]; int find(int x) { if (x != fa[x]) fa[x] = find(fa[x]); return fa[x]; } void merge(int x, int y) { x = find(x); y = find(y); fa[x] = y; } int ok, rd[10010]; void dfs(int r) { int u, v; vector<int> ::iterator it; fa[r] = r; for (it = adj[r].begin(); it != adj[r].end(); ++it) { v = *it; // printf("u=%d v=%d\n", r, v); if (v == a && fa[b]) { printf("%d\n", find(b)); ok = 1; } else if (v == b && fa[a]) { printf("%d\n", find(a)); ok = 1; } if (ok) return; dfs(v); fa[v] = r; } } int main() { int T, i, j, u, v; scanf("%d", &T); while (T--) { scanf("%d", &n); memset(fa, 0, sizeof (fa)); for (i = 1; i <= n; ++i) adj[i].clear(); memset(rd, 0, sizeof (rd)); for (i = 1; i < n; ++i) { scanf("%d%d", &u, &v); adj[u].push_back(v); ++rd[v]; } scanf("%d%d", &a, &b); ok = 0; for (i = 1; i <= n; ++i) if (!rd[i]) dfs(i); } return 0; }
poj1984并查集的路径压缩
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef struct S { int u, v, id, I; } ASK; ASK ask[10010]; int ans[10010]; bool cmp(ASK a, ASK b) { return a.I < b.I; } typedef struct G { int u, v, x, y; } REL; REL rel[40010]; int n, m, q; int fa[40010], rankx[40010], ranky[40010]; int find(int x) { if (x != fa[x]) { int q = fa[x]; fa[x] = find(fa[x]); rankx[x] += rankx[q]; ranky[x] += ranky[q]; } return fa[x]; } void merge(int i) { int a, b; a = find(rel[i].u); b = find(rel[i].v); // printf("i=%d u=%d v=%d a=%d b=%d\n", i, rel[i].u, rel[i].v, a, b); if (a != b) { fa[a] = b; rankx[a] = rankx[rel[i].v] - rankx[rel[i].u] + rel[i].x; ranky[a] = ranky[rel[i].v] - ranky[rel[i].u] + rel[i].y; } } int ABS(int a) { return a < 0 ? -a : a; } void print() { for (int i = 1; i <= n; ++i) { printf("fa%d=%d ranx=%d ranky=%d\n", i, find(i), rankx[i], ranky[i]); } } int main() { int i, d, a, b; char ch[5]; scanf("%d%d", &n, &m); for (i = 1; i <= n; ++i) fa[i] = i; for (i = 1; i <= m; ++i) { scanf("%d%d%d%s", &rel[i].u, &rel[i].v, &d, ch); if (ch[0] == 'N') rel[i].x = 0, rel[i].y = d; else if (ch[0] == 'S') rel[i].x = 0, rel[i].y = -d; else if (ch[0] == 'E') rel[i].x = d, rel[i].y = 0; else rel[i].x = -d, rel[i].y = 0; // printf("rel%d: %d %d %d %d\n", i, rel[i].u, rel[i].v, rel[i].x, rel[i].y); } scanf("%d", &q); for (i = 0; i < q; ++i) { scanf("%d%d%d", &ask[i].u, &ask[i].v, &ask[i].I); ask[i].id = i; } sort(ask, ask + q, cmp); int p = 0; for (i = 1; i <= m;) { while (i == ask[p].I + 1) { // printf("ask%d: u=%d v=%d I=%d\n", p, ask[p].u, ask[p].v, ask[p].I); a = find(ask[p].u); b = find(ask[p].v); if (a != b) { ans[ask[p].id] = -1; } else { ans[ask[p].id] = ABS(rankx[ask[p].u] - rankx[ask[p].v]) + ABS(ranky[ask[p].u] - ranky[ask[p].v]); } ++p; if (p == q) goto L; } merge(i); // print(); ++i; } while (i == ask[p].I + 1) { // printf("ask%d: u=%d v=%d I=%d\n", p, ask[p].u, ask[p].v, ask[p].I); a = find(ask[p].u); b = find(ask[p].v); if (a != b) { ans[ask[p].id] = -1; } else { ans[ask[p].id] = ABS(rankx[ask[p].u] - rankx[ask[p].v]) + ABS(ranky[ask[p].u] - ranky[ask[p].v]); } ++p; if (p == q) break; } L: for (i = 0; i < q; ++i) printf("%d\n", ans[i]); return 0; }
poj1785手写堆
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<string> using namespace std; typedef struct S { char name[50]; int p; } NODE; NODE node[50010]; int L[50010], R[50010]; void gao(int r) { printf("("); if (L[r] != -1) gao(L[r]); printf("%s/%d",node[r].name,node[r].p); // cout << node[r].name << "/" << node[r].p; if (R[r] != -1) gao(R[r]); printf(")"); } bool cmp(const NODE &a, const NODE &b) { return strcmp(a.name, b.name) < 0; } int main() { int n, i, r, t, l; while (scanf("%d", &n) != EOF && n) { r = 0; memset(L, -1, sizeof (L)); memset(R, -1, sizeof (R)); for (i = 0; i < n; ++i) { // getline(cin, node[i].name, '/'); // scanf("%d", &node[i].p); scanf("%*[ ]%[^/]/%d", node[i].name, &node[i].p); // printf("%s/%d\n",node[i].name,node[i].p); } sort(node, node + n, cmp); for (i = 1; i < n; ++i) { if (node[i].p > node[r].p) { L[i] = r; r = i; } else { t = r; while (node[i].p < node[t].p) { if (R[t] == -1) { R[t] = i; goto G; } l = t; t = R[t]; } R[l] = i; L[i] = t; } G: ; } gao(r); printf("\n"); } return 0; }
poj2274记录每辆车的前继和后继,优先队列每次取时刻最小的超车。
#include<cstdio> #include<queue> #include<algorithm> #include<iostream> #include<vector> #include<cstring> using namespace std; #define maxn 250000 int x[maxn + 10], v[maxn + 10]; int cnt_v[110]; long long ans; #define mod 1000000 struct pass { int px, py, tx, ty, a, b; pass() { } pass(int ppx, int ppy, int ttx, int tty, int aa, int bb) : px(ppx), py(ppy), tx(ttx), ty(tty), a(aa), b(bb) { } bool operator>(const pass& temp)const { if ((long long) temp.ty * tx != (long long) ty * temp.tx) return (long long) temp.ty * tx > (long long) ty * temp.tx; return (long long) temp.py * px > (long long) py * temp.px; } } temp; priority_queue<pass, vector<pass>, greater<pass> > q; void gao(int a, int b) { q.push(pass(v[a] * x[b] - v[b] * x[a], v[a] - v[b], x[b] - x[a], v[a] - v[b], a, b)); } int f[maxn + 10], b[maxn + 10]; int main() { int n, i, j; while (scanf("%d", &n) != EOF) { ans = 0; memset(cnt_v, 0, sizeof (cnt_v)); for (i = 0; i < n; ++i) { scanf("%d%d", &x[i], &v[i]); for (j = v[i] + 1; j < 100; ++j) ans += cnt_v[j]; cnt_v[v[i]]++; } printf("%lld\n", ans % mod); if (ans > 10000) ans = 10000; b[0] = -1; f[0] = 1; for (i = 1; i < n; ++i) { b[i] = i - 1; f[i] = i + 1; if (v[i - 1] > v[i]) { gao(i - 1, i); } } f[n - 1] = -1; while (ans--) { temp = q.top(); q.pop(); if (f[temp.a] != temp.b || b[temp.b] != temp.a){ ++ans; continue; } printf("%d %d\n", temp.a + 1, temp.b + 1); b[temp.b] = b[temp.a]; b[temp.a] = temp.b; f[temp.a] = f[temp.b]; f[temp.b] = temp.a; if (b[temp.b] != -1) f[b[temp.b]] = temp.b; if (f[temp.a] != -1) b[f[temp.a]] = temp.a; if (b[temp.b] != -1 && v[b[temp.b]] > v[temp.b]) gao(b[temp.b], temp.b); if (f[temp.a] != -1 && v[temp.a] > v[f[temp.a]]) gao(temp.a, f[temp.a]); } while (!q.empty()) q.pop(); } return 0; }
poj1177扫面线求矩形面积并
#include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<algorithm> #include<iostream> using namespace std; struct EDGE { int l, r, h, f; EDGE() { } EDGE(int ll, int rr, int hh, int ff) : l(ll), r(rr), h(hh), f(ff) { } bool operator<(const EDGE &e) const { return h < e.h; } } edge[10010]; int n, lm, rm, m; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn (1<<16) int cnt[maxn], len[maxn], seg[maxn], lbd[maxn], rbd[maxn]; int ans; void push_up(int l, int r, int rt) { if (cnt[rt]) { lbd[rt] = rbd[rt] = 1; len[rt] = r - l + 1; seg[rt] = 2; } else { if (l == r) { lbd[rt] = rbd[rt] = len[rt] = seg[rt] = 0; } else { lbd[rt] = lbd[rt << 1]; rbd[rt] = rbd[rt << 1 | 1]; len[rt] = len[rt << 1] + len[rt << 1 | 1]; seg[rt] = seg[rt << 1] + seg[rt << 1 | 1]; if (rbd[rt << 1] && lbd[rt << 1 | 1]) seg[rt] -= 2; } } } void update(int L, int R, int f, int l, int r, int rt) { if (L <= l && r <= R) { cnt[rt] += f; push_up(l, r, rt); return; } int m = (l + r) >> 1; if (L <= m) { update(L, R, f, lson); } if (R > m) { update(L, R, f, rson); } push_up(l, r, rt); } int main() { int i, a, b, c, d; scanf("%d", &n); lm = 10001, rm = -10001; for (i = 0; i < n; ++i) { scanf("%d%d%d%d", &a, &c, &b, &d); lm = min(lm, a), rm = max(rm, b - 1); edge[m++] = EDGE(a, b - 1, c, 1); edge[m++] = EDGE(a, b - 1, d, -1); } sort(edge, edge + m); int last = 0; for (i = 0; i < m; ++i) { // printf("i=%d l=%d r=%d h%d f=%d\n", i, edge[i].l, edge[i].r, edge[i].h, edge[i].f); update(edge[i].l, edge[i].r, edge[i].f, lm, rm, 1); // printf("seg=%d len=%d\n", seg[1], len[1]); ans += (edge[i + 1].h - edge[i].h) * seg[1]; ans += abs(len[1] - last); last = len[1]; } printf("%d\n", ans); return 0; }
poj1195二维线段树,单点增加,成块求和
#include<cstdio> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[2100][2100]; int n, core; void push_up2(int x, int rt) { sum[x][rt] = sum[x][rt << 1] + sum[x][rt << 1 | 1]; } void update2(int x, int y, int c, int l, int r, int rt) { // printf("xr=%d y=%d c=%d\n",x,y,c); if (y == l && y == r) { sum[x][rt] += c; return; } int m = (l + r) >> 1; if (y <= m) update2(x, y, c, lson); else update2(x, y, c, rson); push_up2(x, rt); } void update(int x, int y, int c, int l, int r, int rt) { // printf("rt=%d l=%d r=%d\n",rt,l,r); update2(rt, y, c, 0, n - 1, 1); if (x == l && x == r) { return; } int m = (l + r) >> 1; if (x <= m) update(x, y, c, lson); else update(x, y, c, rson); } int query2(int x, int L, int R, int l, int r, int rt) { if (L <= l && r <= R) return sum[x][rt]; int m = (l + r) >> 1, temp = 0; if (L <= m) temp += query2(x, L, R, lson); if (R > m) temp += query2(x, L, R, rson); return temp; } int query(int L, int R, int b, int t, int l, int r, int rt) { if (L <= l && r <= R) return query2(rt, b, t, 0, n - 1, 1); int m = (l + r) >> 1, temp = 0; if (L <= m) temp += query(L, R, b, t, lson); if (R > m) temp += query(L, R, b, t, rson); return temp; } int main() { int op, x, y, c, l, r, b, t; scanf("%d%d", &op, &n); while (scanf("%d", &op) != EOF && op < 3) { if (op == 1) { scanf("%d%d%d", &x, &y, &c); update(x, y, c, 0, n - 1, 1); } else { scanf("%d%d%d%d", &l, &b, &r, &t); if (l < 0) l = 0; if (b < 0) b = 0; if (r >= n) r = n - 1; if (t >= n) t = n - 1; printf("%d\n", query(l, r, b, t, 0, n - 1, 1)); } } return 0; }
poj2750线段树,单点更新,求成段最值。利用最大和最小的转换解决环的问题。
#include<cstdio> #include<cstring> #define maxn (1<<18) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[maxn], smax[maxn], smin[maxn], lmax[maxn], lmin[maxn], rmax[maxn], rmin[maxn]; inline int max(int a, int b) { return a > b ? a : b; } inline int min(int a, int b) { return a < b ? a : b; } void push_up(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; smax[rt] = max(max(smax[rt << 1], smax[rt << 1 | 1]), rmax[rt << 1] + lmax[rt << 1 | 1]); smin[rt] = min(min(smin[rt << 1], smin[rt << 1 | 1]), rmin[rt << 1] + lmin[rt << 1 | 1]); lmax[rt] = max(lmax[rt << 1], sum[rt << 1] + lmax[rt << 1 | 1]); lmin[rt] = min(lmin[rt << 1], sum[rt << 1] + lmin[rt << 1 | 1]); rmax[rt] = max(rmax[rt << 1 | 1], sum[rt << 1 | 1] + rmax[rt << 1]); rmin[rt] = min(rmin[rt << 1 | 1], sum[rt << 1 | 1] + rmin[rt << 1]); } void update(int i, int x, int l, int r, int rt) { if (i == l && i == r) { sum[rt] = smax[rt] = smin[rt] = lmax[rt] = lmin[rt] = rmax[rt] = rmin[rt] = x; return; } int m = (l + r) >> 1; if (i <= m) update(i, x, lson); else update(i, x, rson); push_up(rt); } int main() { int n, i, x, j, m; scanf("%d", &n); for (i = 1; i <= n; ++i) { scanf("%d", &x); update(i, x, 1, n, 1); } scanf("%d", &m); for (i = 0; i < m; ++i) { scanf("%d%d", &j, &x); update(j, x, 1, n, 1); if (sum[1] == smax[1]) { printf("%d\n", sum[1] - smin[1]); } else { printf("%d\n", max(smax[1], sum[1] - smin[1])); } } return 0; }
Assignment 3: Data Structures
最新推荐文章于 2024-06-17 17:25:34 发布