hdu 4605 Magic Ball Game
树状数组在dfs的应用,比较适合求区间的和#include <cstdio> #include <iostream> #include <algorithm> #include <vector> #include <cstring> using namespace std; #define MAXN 100010 /** 从1到v的路径固定,按照dfs的思想,等同于只考虑 一条支路;在一条支路上分为左右部分,找出大于x的 个数和小于x的个数 */ int n, m, q; int w[MAXN], cnt, d[MAXN<<1], res[MAXN<<1][2], ans[MAXN][2]; struct node {int a, b; node(int _a, int _b):a(_a),b(_b){}}; vector<int> son[MAXN]; vector<node> mp[MAXN]; int lowbit(int c) { return c & -c; } void update(int u, int c, int val) { for (int i = u; i <= cnt; i += lowbit(i)) res[i][c] += val; } int getSum(int u, int c) { int sum = 0; for (int i = u; i > 0; i -= lowbit(i)) sum += res[i][c]; return sum; } int top, stk[MAXN]; int cson[MAXN], mpot[MAXN]; void dfs() { top = 0; stk[top++] = 1; memset(cson, 0, sizeof cson); int u, i, s; int wei, dx, p, la, ra, lb, rb, lc, rc; int v, wv; while (top) { u = stk[top-1]; if (cson[u] == 0) { s = mp[u].size(); for (i = 0; i< s; ++i) { wei = mp[u][i].b; dx = mp[u][i].a; p = lower_bound(d, d+cnt, wei)-d+1; la = getSum(p-1, 0); ra = getSum(p-1, 1); lb = getSum(cnt, 0); rb = getSum(cnt, 1); lc = lb - getSum(p, 0); rc = rb - getSum(p, 1); if (la+ra+lc+rc - lb - rb) { ans[dx][1] = -1; continue; } ans[dx][0] = ra; ans[dx][1] = (la+ra)*3 + lc + rc; } } if (son[u].size() == 0) { top--; continue; } s = cson[u]; if (s & 0x1) { update(mpot[u], s>>1, -1); s = ++cson[u]; if (s > 3) { --top; continue; } } v = son[u][s>>1]; wv = w[u]; mpot[u] = p = lower_bound(d, d+cnt, wv)-d+1; update(p, s>>1, 1); stk[top++] = v; cson[u]++; } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif // ONLINE_JUDGE int t, i; int u, a, b, x, v; scanf("%d", &t); while (t--) { scanf("%d", &n); cnt = 0; for (i = 0; i<= n; ++i) { son[i].clear(); } for (i = 1; i<= n; ++i) { scanf("%d", &w[i]); d[cnt++] = w[i]; } scanf("%d", &m); for (i = 0; i< m; ++i) { scanf("%d%d%d", &u, &a, &b); son[u].push_back(a); son[u].push_back(b); } scanf("%d", &q); for (i = 0; i<= q; ++i) mp[i].clear(); for (i = 0; i< q; ++i) { scanf("%d%d", &v, &x); mp[v].push_back(node(i, x)); d[cnt++] = x; } sort(d, d+cnt); cnt = unique(d, d+cnt)-d; memset(res, 0, sizeof res); dfs(); for (i = 0; i< q; ++i) { if (ans[i][1] == -1) printf("0\n"); else printf("%d %d\n", ans[i][0], ans[i][1]); } } return 0; }
hdu 4630 No Pain No Game
树状数组、离散化#include <cstdio> #include <iostream> #include <cmath> #include <algorithm> using namespace std; const int MAXN = 50005; int n; int a[MAXN]; int tree[MAXN], pre[MAXN], res[MAXN]; int lowbit(int i) { return i & (-i); } void add(int pos, int val) { while (pos <= n) { tree[pos] = max(tree[pos], val); pos += lowbit(pos); } } int solve(int i) { int r = 0; while (i > 0) { r = max(r, tree[i]); i -= lowbit(i); } return r; } struct node { int idx, l, r; bool operator < (const node & e) const { return l > e.l; } void getin() { scanf("%d%d", &l, &r); } }query[MAXN]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 1; i<= n; ++i) { scanf("%d", a+i); } int q; scanf("%d", &q); for (int i = 0; i< q; ++i) { query[i].getin(); query[i].idx = i; } sort(query, query+q); memset(tree, 0, sizeof tree); memset(pre, 0, sizeof pre); for (int i = 0, j = n; i< q; ) { for (; j>0 && j >= query[i].l; --j) { for(int k = 1; k*k <= a[j]; ++k) { if (a[j] % k == 0) { if (pre[k]) { add(pre[k], k); } pre[k] = j; if (k != a[j]/k) { if (pre[a[j]/k]) { add(pre[a[j]/k], a[j]/k); } pre[a[j]/k] = j; } } } } while (i < q && query[i].l > j) { res[query[i].idx] = solve(query[i].r); ++i; } } for (int i = 0; i < q; ++i) printf("%d\n", res[i]); } return 0; }
hdu 4638 Group
与上一题类似#include <cstdio> #include <algorithm> using namespace std; const int MAXN = 100005; int sum[MAXN], a[MAXN]; int ans[MAXN]; int vis[MAXN]; int n, m; // sum[i] 代表 struct qy { int s, e, id; bool operator < (const qy & v) const { return s < v.s; } void getin(int k) { id = k; scanf("%d%d", &s, &e); } }q[MAXN]; int lowbit(int i) { return i &(-i); } void add(int i, int val) { while (i<= n) { sum[i] += val; i += lowbit(i); } } int query(int i) { int num = 0; while (i > 0) { num += sum[i]; i -= lowbit(i); } return num; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); for (int i = 1; i<= n; ++i) { scanf("%d", a+i); } memset(sum, 0, sizeof sum); memset(vis, 0, sizeof vis); for (int i = 1; i<= m; ++i) { q[i].getin(i); } sort(q+1, q+1+m); int k = m; for (int i = n; i>= 1; --i) { int tp = a[i]; vis[tp] = i; add(i, 1); if (vis[tp+1]) add(vis[tp+1], -1); if (vis[tp-1]) add(vis[tp-1], -1); while (k >= 1 && q[k].s == i) { ans[q[k].id] = query(q[k].e) - query(i-1); k--; } } for (int i = 1; i<= m; ++i) { printf("%d\n", ans[i]); } } return 0; }
hdu 4777 Rabbit Kingdom
树状数组求解区间内互质的数个数
#include <cstdio> #include <iostream> #include <cmath> #include <map> #include <algorithm> #include <vector> using namespace std; const int MAXN = 200010; int n, m; int sum[MAXN], isprm[MAXN], prime[MAXN], nprm; int num[MAXN], cp[MAXN][15], LL[MAXN], RR[MAXN], U[MAXN], O[MAXN], ans[MAXN]; vector<int> mmp[MAXN]; struct _query { int l, r, d; bool operator < (const _query & a) const { return r < a.r; } }query[MAXN]; void getprime() { nprm = 0; for (int i = 2; i< 500; ++i) { if (isprm[i] == 0) prime[nprm++] = i; for (int j = 0; j<nprm && i*prime[j] < MAXN; ++j) { isprm[i*prime[j]] = 1; if (i % prime[j] == 0) break; } } } int lowbit(int c){ return c&-c; } void add(int u, int val) { if (!u) return; while (u <= n) { sum[u] += val; u += lowbit(u); } } int getsum(int u) { int res = 0; while (u > 0) { res += sum[u]; u -= lowbit(u); } return res; } void dividePrime(int idx) { int tp = num[idx]; cp[idx][0] = 0; for (int i = 0; i< nprm && prime[i]*prime[i]<=tp ; ++i) { if (tp % prime[i] == 0) { cp[idx][++cp[idx][0]] = prime[i]; while (tp % prime[i] == 0) tp/=prime[i]; } } if (tp != 1) cp[idx][++cp[idx][0]] = tp; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int idx; getprime(); while (scanf("%d%d", &n, &m) && (n+m)) { for (int i = 1; i<= n; ++i) scanf("%d", num+i); for (int i = 0; i< m; ++i) { scanf("%d%d", &query[i].l, &query[i].r); query[i].d = i; } sort(query, query+m); memset(sum, 0, sizeof sum); for (int i = 1; i<= n; ++i) dividePrime(i), LL[i] = 0, RR[i] = n+1; for (int i = 0; i< MAXN; ++i) U[i] = 0, O[i] = n+1; for (int i = 1; i<= n; ++i) { for (int j = 1, k=cp[i][0]; j<= k; ++j) { LL[i] = max(LL[i], U[cp[i][j]]); U[cp[i][j]] = i; } } for (int i = n; i>= 1; --i) { for (int j = 1, k=cp[i][0]; j<= k; ++j) { RR[i] = min(RR[i], O[cp[i][j]]); O[cp[i][j]] = i; } } for (int i = 1; i<= n; ++i) mmp[i].clear(); for (int i = 1; i<= n; ++i) mmp[RR[i]].push_back(i); idx = 1; for (int i = 0; i< m; ++i) { while (idx <= query[i].r && idx <= n) { add(LL[idx], 1); for (int a, j = 0, k=mmp[idx].size(); j<k; ++j) { a = mmp[idx][j]; add(LL[a], -1); add(a, 1); } ++idx; } ans[query[i].d] = getsum(query[i].r) - getsum(query[i].l-1); ans[query[i].d] = query[i].r-query[i].l+1 - ans[query[i].d]; } for (int i = 0; i< m; ++i) printf("%d\n", ans[i]); } return 0; }