链接:
codeforces.com/contest/853/problem/C
题意:
给你一个区域内上n个点,每次查询一个矩形区域,问有多少对点的连线经过这个矩形
题解:
把整个区域分为9个部分
1 2 3
4 5 6
7 8 9
查询的区域即为5,这样估计都能看出来结果了
查询每一个小的区域有多少个点用主席树就可以了,主席树的一个重要用途就是求区间[l, r]中的值介于[x,y]的值。
代码:
31 struct Node { int l, r, sum; }; 32 int n, q; 33 Node T[MAXN * 40]; 34 int root[MAXN], cnt; 35 36 void update(int l, int r, int &x, int y, int pos) { 37 T[++cnt] = T[y], T[cnt].sum++, x = cnt; 38 if (l == r) return; 39 int m = (l + r) >> 1; 40 if (pos <= m) update(l, m, T[x].l, T[y].l, pos); 41 else update(m + 1, r, T[x].r, T[y].r, pos); 42 } 43 44 int query(int l, int r, int R, int L, int D, int U) { 45 if (D > U) return 0; 46 if (D <= l && r <= U) return T[R].sum - T[L].sum; 47 int m = (l + r) >> 1, ret = 0; 48 if (D <= m) ret += query(l, m, T[R].l, T[L].l, D, U); 49 if (U > m) ret += query(m + 1, r, T[R].r, T[L].r, D, U); 50 return ret; 51 } 52 53 int main() { 54 ios::sync_with_stdio(false), cin.tie(0); 55 cin >> n >> q; 56 rep(i, 1, n + 1) { 57 int x; 58 cin >> x; 59 update(1, n, root[i], root[i - 1], x); 60 } 61 while (q--) { 62 int l, d, r, u; 63 cin >> l >> d >> r >> u; 64 ll cnt1 = query(1, n, root[l - 1], root[0], u + 1, n); 65 ll cnt2 = query(1, n, root[r], root[l - 1], u + 1, n); 66 ll cnt3 = query(1, n, root[n], root[r], u + 1, n); 67 ll cnt4 = query(1, n, root[l - 1], root[0], d, u); 68 ll cnt5 = query(1, n, root[r], root[l - 1], d, u); 69 ll cnt6 = query(1, n, root[n], root[r], d, u); 70 ll cnt7 = query(1, n, root[l - 1], root[0], 1, d - 1); 71 ll cnt8 = query(1, n, root[r], root[l - 1], 1, d - 1); 72 ll cnt9 = query(1, n, root[n], root[r], 1, d - 1); 73 ll ans = 0; 74 ans += cnt1*(cnt5 + cnt6 + cnt8 + cnt9); 75 ans += cnt2*(cnt4 + cnt5 + cnt6 + cnt7 + cnt8 + cnt9); 76 ans += cnt3*(cnt4 + cnt5 + cnt7 + cnt8); 77 ans += cnt4*(cnt2 + cnt3 + cnt5 + cnt6 + cnt8 + cnt9); 78 ans += cnt5*(n - 1); 79 ans += cnt6*(cnt1 + cnt2 + cnt4 + cnt5 + cnt7 + cnt8); 80 ans += cnt7*(cnt2 + cnt3 + cnt5 + cnt6); 81 ans += cnt8*(cnt1 + cnt2 + cnt3 + cnt4 + cnt5 + cnt6); 82 ans += cnt9*(cnt1 + cnt2 + cnt4 + cnt5); 83 cout << ans / 2 << endl; 84 } 85 return 0; 86 }