# BZOJ3262陌上花开（三维偏序问题（CDQ分治+树状数组））+CDQ分治基本思想

emmmm我能怎么说呢

CDQ分治显然我没法写一篇完整的优秀的博客，因为我自己还不是很明白...

fateice如是说道：

（图片来自fateice大爷的怕怕踢）

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

## Sample Output

3
1
3
0
1
0
1
0
0
1

emmm读完题目后我们显然的可以想到这是三维偏序的CDQ分治的基本题

 1 #include<bits/stdc++.h>
2 #define ll long long
3 #define uint unsigned int
4 #define ull unsigned long long
5 using namespace std;
6 const int maxn = 100010;
7 struct Query {
8     int s, c, m;
9     int num, sum;
10     bool operator < (const Query &A) const {
11         return c == A.c ? m < A.m : c < A.c;
12     }
13     bool operator != (const Query &A) const {
14         return s != A.s || c != A.c || m != A.m;
15     }
16 }a[maxn], q[maxn];
17 int n, k, cnt = 0, top = 0;
18 int c[maxn << 1];
19 int ans[maxn];
20
22     int x = 0, y = 1;
23     char ch = getchar();
24     while(!isdigit(ch)) {
25         if(ch == '-') y = -1;
26         ch = getchar();
27     }
28     while(isdigit(ch)) {
29         x = (x << 1) + (x << 3) + ch - '0';
30         ch = getchar();
31     }
32     return x * y;
33 }
34
35 inline bool cmp(Query x, Query y) {//按第一维排序
36     if(x.s == y.s && x.c == y.c) return x.m < y.m;
37     else if(x.s == y.s) return x.c < y.c;
38     return x.s < y.s;
39 }
40
41 inline int ask(int x) {
42     int res = 0;
43     for(; x; x -= (x & -x)) res += c[x];
44     return res;
45 }
46
47 inline void add(int x, int y) {
48     for(; x <= k; x += (x & -x)) c[x] += y;
49 }
50
51 void solve(int l, int r) {
52     if(l == r) return;
53     int mid = l + r >> 1;
54     solve(l, mid), solve(mid + 1, r);
55     sort(q + l, q + mid + 1);//排序，让我sb的卡了会，因为不知道sort的排序是左闭右开
56     sort(q + mid + 1, q + r + 1);
57     int x = l;
58     for(int i = mid + 1; i <= r; ++i) {//用左边区间的答案导出右边区间的答案
59         while(x <= mid && q[x].c <= q[i].c) add(q[x].m, q[x].num), x++;//确定了前两维的顺序时，将q[x].m赋上该品种的花的数量，方便右边区间查询
61     }
62     for(int i = l; i < x; ++i) add(q[i].m, -q[i].num);//还原树状数组
63 }
64
65 int main() {
67     for(int i = 1; i <= n; ++i)
69     sort(a + 1, a + n + 1, cmp);
70     for(int i = 1; i <= n; ++i) {
71         cnt++;
72         if(a[i] != a[i + 1]) {
73             q[++top] = a[i];
74             q[top].num = cnt;//对于某一品种花有多少个
75             cnt = 0;
76         }
77     }
78     solve(1, top);
79     for(int i = 1; i <= top; ++i) ans[q[i].sum + q[i].num - 1] += q[i].num;
80     //一朵花的评级=该朵花的美丽值超越的花的数量+属性相同的花的总量(包含自己)-1
81     //因为题目：定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。
82     for(int i = 0; i < n; ++i) printf("%d\n", ans[i]);
83     //评级可能有0的
84     return 0;
85 }

posted @ 2019-02-18 21:10 YuWenjue 阅读(...) 评论(...) 编辑 收藏