区间第K大
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | /************************************************************************* > File Name: hdu2665.cpp > Author: skt > Mail: sktsxy@gmail.com > Created Time: 2015年10月05日 星期一 15时56分48秒 ************************************************************************/ #include <cstring> #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <queue> #include <bitset> #include <algorithm> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <complex> #include <cassert> // #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define LL long long #define pb push_back #define mp make_pair #define x first #define y second #define MAXN 100005 template <typename T> inline void checkMax(T &a, T b) {a = a>b?a:b;} template <typename T> inline void checkMin(T &a, T b) {a = a<b?a:b;} typedef pair<int, int> PII; typedef vector<int> vi; const double PI = acos(-1.0); const double eps = 1e-8; int T, N, Q, a[MAXN], b[MAXN], n; struct Node { int l, r, sum; } p[MAXN * 20]; int root[MAXN], tot; void build(int l, int r, int &rt) { rt = ++ tot; p[rt].l = p[rt].r = 0; p[rt].sum = 0; if (l == r) return ; int mid = (l + r) >> 1; build(l, mid, p[rt].l); build(mid + 1, r, p[rt].r); } void update(int pr, int l, int r, int ins, int &rt) { rt = ++ tot; p[rt] = p[pr]; p[rt].sum ++; if (l == r) { return ; } int mid = (l + r) >> 1; if (ins <= mid) { update(p[pr].l, l, mid, ins, p[rt].l); } else { update(p[pr].r, mid + 1, r, ins, p[rt].r); } } int query(int lr, int rr, int l, int r, int k) { if (l == r) return r; int mid = (l + r) >> 1; int left = p[p[rr].l].sum - p[p[lr].l].sum; if (left >= k) return query(p[lr].l, p[rr].l, l, mid, k); else return query(p[lr].r, p[rr].r, mid + 1, r, k - left); } void work() { scanf("%d %d", &N, &Q); for (int i = 1; i <= N; i ++) { scanf("%d", &a[i]); b[i] = a[i]; } tot = 0; sort(b + 1, b + 1 + N); n = unique(b + 1, b + 1 + N) - b - 1; build(1, n, root[0]); for (int i = 1; i <= N; i ++) { int pos = lower_bound(b + 1, b + 1 + n, a[i]) - b; update(root[i - 1], 1, n, pos, root[i]); } for (int i = 1; i <= Q; i ++) { int l, r, k; scanf("%d %d %d", &l, &r, &k); cout << b[query(root[l - 1], root[r], 1, n, k)] << endl; } } int main() { scanf("%d", &T); while (T --) { work(); } return 0; } |
树上第K大
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | /************************************************************************* > File Name: spoj_cot.cpp > Author: skt > Mail: sktsxy@gmail.com > Created Time: 2015年10月24日 星期六 23时41分58秒 ************************************************************************/ #include <cstring> #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <queue> #include <bitset> #include <algorithm> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <complex> #include <cassert> // #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define LL long long #define pb push_back #define mp make_pair #define x first #define y second #define MAXN 100005 template <typename T> inline void checkMax(T &a, T b) {a = a>b?a:b;} template <typename T> inline void checkMin(T &a, T b) {a = a<b?a:b;} typedef pair<int, int> PII; typedef vector<int> vi; const double PI = acos(-1.0); const double eps = 1e-8; int N, M, a[MAXN], b[MAXN], H; int head[MAXN], cnt; struct Edge { int v, next; } p[MAXN << 1]; struct Node { int ls, rs, sum; } Segs[MAXN * 20]; int root[MAXN], tot; void init() { fill(head, head + MAXN, -1); cnt = 0; tot = 0; memset(root, 0, sizeof(root)); } void addEdge(int u, int v) { p[cnt].v = v; p[cnt].next = head[u]; head[u] = cnt ++; } void hash_init() { for (int i = 1; i <= N; i ++) { b[i] = a[i]; } sort(b + 1, b + 1 + N); H = unique(b + 1, b + 1 + N) - b - 1; for (int i = 1; i <= N; i ++) { a[i] = lower_bound(b + 1, b + 1 + H, a[i]) - b; } } void build(int l, int r, int &rt) { rt = ++ tot; Segs[rt].sum = 0; if (l == r) { Segs[rt].ls = Segs[rt].rs = 0; return ; } int mid = (l + r) >> 1; build(l, mid, Segs[rt].ls); build(mid + 1, r, Segs[rt].rs); } void update(int l, int r, int ins, int &rt, int fa) { rt = ++ tot; Segs[rt] = Segs[fa]; Segs[rt].sum ++; if (l == r) { return ; } int mid = (l + r) >> 1; if (ins <= mid) { update(l, mid, ins, Segs[rt].ls, Segs[fa].ls); } else { update(mid + 1, r, ins, Segs[rt].rs, Segs[fa].rs); } } int query(int l, int r, int k, int a, int b, int fab, int ffab) { if (l == r) return l; int mid = (l + r) >> 1; int goal = Segs[Segs[a].ls].sum + Segs[Segs[b].ls].sum - Segs[Segs[fab].ls].sum - Segs[Segs[ffab].ls].sum; if (goal >= k) { return query(l, mid, k, Segs[a].ls, Segs[b].ls, Segs[fab].ls, Segs[ffab].ls); } else { return query(mid + 1, r, k - goal, Segs[a].rs, Segs[b].rs, Segs[fab].rs, Segs[ffab].rs); } } int id[MAXN * 2], depth[MAXN], f[MAXN], flag, dp[MAXN * 2][20], lca[MAXN * 2][20], pre[MAXN]; void dfs(int u, int fa, int dep) { pre[u] = fa; depth[u] = dep; id[++ flag] = u; f[u] = flag; update(1, H, a[u], root[u], root[fa]); for (int i = head[u]; i != -1; i = p[i].next) { int v = p[i].v; if (v != fa) { dfs(v, u, dep + 1); id[++ flag] = u; } } } void rmq_init(int n) { for (int i = 1; i <= n; i ++) { dp[i][0] = depth[id[i]], lca[i][0] = id[i]; } for (int j = 1; j <= log(double(n + 1)) / log(2.0); j ++) { for (int i = 1; i + (1 << j) - 1 <= n; i ++) { if (dp[i][j - 1] < dp[i + (1 << (j - 1))][j - 1]) { dp[i][j] = dp[i][j - 1]; lca[i][j] = lca[i][j - 1]; } else { dp[i][j] = dp[i + (1 << (j - 1))][j - 1]; lca[i][j] = lca[i + (1 << (j - 1))][j - 1]; } } } } int rmq(int l, int r) { int L = f[l], R = f[r]; if (R < L) swap(R, L); int k = (int)(log((double)(R - L + 1)) / log(2.0)); if (dp[L][k] < dp[R - (1 << k) + 1][k]) { return lca[L][k]; } else { return lca[R - (1 << k) + 1][k]; } } void work() { flag = 0; init(); for (int i = 1; i <= N; i ++) { scanf("%d", &a[i]); } hash_init(); for (int i = 1; i < N; i ++) { int u, v; scanf("%d %d", &u, &v); addEdge(u, v); addEdge(v, u); } build(1, H, root[0]); dfs(1, 0, 1); rmq_init(2 * N - 1); for (int i = 1; i <= M; i ++) { int u, v, k; scanf("%d %d %d", &u, &v, &k); int fuv = rmq(u, v); int h = query(1, H, k, root[u], root[v], root[fuv], root[pre[fuv]]); printf("%d\n", b[h]); } } int main() { #ifdef __SKT__ freopen("in", "r", stdin); #endif while (scanf("%d %d", &N, &M) != EOF) { work(); } return 0; } |
题意:给两个树,有N个查询,每次询问第一个树的一个点和第二个树上的一个点,最先相同下标点是什么?强制在线
算法:可持久化数据结构A树维护到根到这个点里B树的位置,然后树链剖分B树的区间,查询.复杂度为
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | /************************************************************************* > File Name: f.cpp > Author: skt > Mail: sktsxy@gmail.com > Created Time: 2015年10月28日 星期三 15时24分07秒 ************************************************************************/ #include <cstring> #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <queue> #include <bitset> #include <algorithm> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <complex> #include <cassert> // #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define LL long long #define pb push_back #define mp make_pair #define x first #define y second #define MAXN 100005 template <typename T> inline void checkMax(T &a, T b) {a = a>b?a:b;} template <typename T> inline void checkMin(T &a, T b) {a = a<b?a:b;} typedef pair<int, int> PII; typedef vector<int> vi; const double PI = acos(-1.0); const double eps = 1e-8; int N, M; vector<int> search[MAXN]; struct Graph { int head[MAXN], cnt; struct Edge { int v, next; } p[MAXN << 1]; void init() { fill(head, head + MAXN, -1); cnt = 0; } void addEdge(int u, int v) { p[cnt].v = v; p[cnt].next = head[u]; head[u] = cnt ++; } void input() { for (int i = 2; i <= N; i ++) { int pre; scanf("%d", &pre); addEdge(i, pre); addEdge(pre, i); } } } wife, husband; struct Node { int l, r, v; } Segs[MAXN * 20]; int root[MAXN], tot; int disA[MAXN], disB[MAXN]; int fa[MAXN], sz[MAXN], depth[MAXN], son[MAXN], top[MAXN], w[MAXN], id[MAXN], total; void build(int l, int r, int &rt) { rt = ++ tot; Segs[rt].l = Segs[rt].r = 0; Segs[rt].v = 0; if (l == r) return ; int mid = (l + r) >> 1; build(l, mid, Segs[rt].l); build(mid + 1, r, Segs[rt].r); } void update(int l, int r, int ins, int &rt, int pre, int v) { rt = ++ tot; Segs[rt] = Segs[pre]; Segs[rt].v = max(Segs[rt].v, v); if (l == r) return ; int mid = (l + r) >> 1; if (ins <= mid) { update(l, mid, ins, Segs[rt].l, Segs[pre].l, v); } else { update(mid + 1, r, ins, Segs[rt].r, Segs[pre].r, v); } } void dfs(int u, int fa, int dep) { disA[u] = dep; update(1, N, w[u], root[u], root[fa], u); for (int i = wife.head[u]; i != -1; i = wife.p[i].next) { int v = wife.p[i].v; if (v != fa) { dfs(v, u, dep + 1); } } } void dfs1(int u, int pre, int dep) { disB[u] = dep; fa[u] = pre, sz[u] = 1, depth[u] = dep, son[u] = 0; for (int i = husband.head[u]; i != -1; i = husband.p[i].next) { int v = husband.p[i].v; if (v != pre) { dfs1(v, u, dep + 1); sz[u] += sz[v]; if (sz[son[u]] < sz[v]) { son[u] = v; } } } } void dfs2(int u, int tp) { w[u] = ++ total; id[total] = u; top[u] = tp; if (son[u]) { dfs2(son[u], tp); } for (int i = husband.head[u]; i != -1; i = husband.p[i].next) { int v = husband.p[i].v; if (v != fa[u] && v != son[u]) { dfs2(v, v); } } } int ask(int l, int r, int L, int R, int rt) { if (l <= L && R <= r) { return Segs[rt].v; } int mid = (L + R) >> 1; int ans = 0; if (mid >= l) { ans = max(ans, ask(l, r, L, mid, Segs[rt].l)); } if (mid < r) { ans = max(ans, ask(l, r, mid + 1, R, Segs[rt].r)); } return ans; } void work() { total = 0; wife.init(); husband.init(); wife.input(); husband.input(); dfs1(1, 0, 1); dfs2(1, 1); tot = 0; build(1, N, root[0]); dfs(1, 0, 1); int ans = 0; for (int i = 1; i <= M; i ++) { int l, r; scanf("%d %d", &l, &r); l = (l + ans) % N + 1; r = (r + ans) % N + 1; int res = 0; int ansL = disA[l], ansR = disB[r]; while (top[r] != 1) { res = max(res, ask(w[top[r]], w[r], 1, N, root[l])); r = fa[top[r]]; } res = max(res, ask(w[top[r]], w[r], 1, N, root[l])); ansL = ansL - disA[res] + 1; ansR = ansR - disB[res] + 1; cout << res << " " << ansL << " " << ansR << endl; ans = res; } } int main() { #ifdef __SKT__ freopen("in", "r", stdin); #endif while (scanf("%d %d", &N, &M) != EOF) { work(); } return 0; } |
题解:一共Q个查询,查询[l,r]区间里,最接近k的数
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | /************************************************************************* > File Name: hiho1169.cpp > Author: skt > Mail: sktsxy@gmail.com > Created Time: 2015年11月06日 星期五 23时08分14秒 ************************************************************************/ #include <cstring> #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <queue> #include <bitset> #include <algorithm> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <complex> #include <cassert> // #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define LL long long #define pb push_back #define mp make_pair #define x first #define y second #define MAXN 200005 template <typename T> inline void checkMax(T &a, T b) {a = a>b?a:b;} template <typename T> inline void checkMin(T &a, T b) {a = a<b?a:b;} typedef pair<int, int> PII; typedef vector<int> vi; const double PI = acos(-1.0); const double eps = 1e-8; const LL INF = 1000000000000LL; int T, Cas = 1, N, Q; int a[MAXN], b[MAXN], bn; struct Node { int l, r, cnt; } Segs[MAXN * 40]; int tot, root[MAXN]; void build(int l, int r, int &rt) { rt = ++ tot; Segs[rt].l = Segs[rt].r = Segs[rt].cnt = 0; if (l == r) return ; int mid = (l + r) >> 1; build(l, mid, Segs[rt].l); build(mid + 1, r, Segs[rt].r); } void update(int l, int r, int pr, int &rt, int ins) { rt = ++ tot; Segs[rt] = Segs[pr]; Segs[rt].cnt ++; if (l == r) return ; int mid = (l + r) >> 1; if (ins <= mid) { update(l, mid, Segs[pr].l, Segs[rt].l, ins); } else { update(mid + 1, r, Segs[pr].r, Segs[rt].r, ins); } } void hash_init() { sort(b + 1, b + 1 + N); bn = unique(b + 1, b + 1 + N) - b - 1; for (int i = 1; i <= N; i ++) { a[i] = lower_bound(b + 1, b + 1 + bn, a[i]) - b; } } int query1(int l, int r, int pr, int rt, int ins) { if (l == r) { int num = Segs[rt].cnt - Segs[pr].cnt; return num ? l : 0; } int mid = (l + r) >> 1; int rightnum = Segs[Segs[rt].r].cnt - Segs[Segs[pr].r].cnt; int leftnum = Segs[Segs[rt].l].cnt - Segs[Segs[pr].l].cnt; if ((rightnum + leftnum) == 0) return 0; if (ins <= mid) { return query1(l, mid, Segs[pr].l, Segs[rt].l, ins); } else { int q = query1(mid + 1, r, Segs[pr].r, Segs[rt].r, ins); if (q) { return q; } if (leftnum == 0) return 0; return query1(l, mid, Segs[pr].l, Segs[rt].l, ins); } } int query2(int l, int r, int pr, int rt, int ins) { if (l == r) { int num = Segs[rt].cnt - Segs[pr].cnt; return num ? l : 0; } int mid = (l + r) >> 1; int rightnum = Segs[Segs[rt].r].cnt - Segs[Segs[pr].r].cnt; int leftnum = Segs[Segs[rt].l].cnt - Segs[Segs[pr].l].cnt; if (leftnum + rightnum == 0) return 0; if (ins <= mid) { int q = query2(l, mid, Segs[pr].l, Segs[rt].l, ins); if (q) { return q; } if (rightnum == 0) return 0; return query2(mid + 1, r, Segs[pr].r, Segs[rt].r, ins); } else { return query2(mid + 1, r, Segs[pr].r, Segs[rt].r, ins); } } void work() { printf("Case #%d:\n", Cas ++); scanf("%d %d", &N, &Q); for (int i = 1; i <= N; i ++) { scanf("%d", &a[i]); b[i] = a[i]; } hash_init(); tot = 0; build(1, bn, root[0]); for (int i = 1; i <= N; i ++) { update(1, bn, root[i - 1], root[i], a[i]); } for (int i = 1; i <= Q; i ++) { int l, r, k; scanf("%d %d %d", &l, &r, &k); int big = upper_bound(b + 1, b + 1 + bn, k) - b; int small = big - 1; LL res = INF; if (small) { int q1 = query1(1, bn, root[l - 1], root[r], small); if (q1) { res = min(res, (LL)abs(b[q1] - k)); } } if (big <= bn) { int q1 = query2(1, bn, root[l - 1], root[r], big); if (q1) { res = min(res, (LL)abs(b[q1] - k)); } } printf("%lld\n", res); } } int main() { scanf("%d", &T); while (T --) { work(); } return 0; } |