Codeforces Round #433 (Div. 1, based on Olympiad of Metropolises) C. Boredom 主席树

链接:

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 }

 

posted @ 2017-09-19 14:47  Flowersea  阅读(115)  评论(0编辑  收藏  举报