模板 三维偏序

传送门


题目大意

空间内有$n$个点$(x_i,y_i,z_i)$。
定义$f(i)=\sum_{j=1}^n [x_j\le x_i, y_j\le x_j, z_j\le z_i, i \not=j]$。
求$f(i),i\in[0,n)$。

解法

首先可以把所有的点按第一维排序。
然后对于第二维,对与所有第二维大于等于这个点的位置记录存在一个这个点的第三维。
然后就可以简单地用平衡树统计第三维得出答案了。
第二维的话就可以简单的用一下树状数组搞一搞。

由于题目中可以大于等于,那么我们把所有第一维相同的全部记录完再算它们的答案。
具体看代码喽。

Code

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
#define DREP(i, s, e) for(int i = s; i >= e ;i--)
#define REP(i, s, e) for(int i = s; i <= e ;i++)

#define DEBUG fprintf(stderr, "Passing [%s] in Line %d\n", __FUNCTION__, __LINE__)
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1000000 + 10, maxk = 2000000;

template <typename T> inline T read()
{
T ans(0), p(1);
char c = getchar();
while (!isdigit(c))
{
if (c == '-') p = -1;
c = getchar();
}
while (isdigit(c))
{
ans = ans * 10 + c - 48;
c = getchar();
}
return ans * p;
}

int n, k;
struct flower
{
int s, c, m, id;
flower(){}
flower(int _s, int _c, int _m, int _id) : s(_s), c(_c), m(_m), id(_id){}
}f[maxn];
bool cmp(flower A, flower B) {return A.s < B.s;}

vector <int> s[maxn];
void update(int c, int m)
{
while (c <= k)
{
s[c].insert(lower_bound(s[c].begin(), s[c].end(), m), m);
c += c & -c;
}
// REP(i, c, cmax)s[i].insert(lower_bound(s[i].begin(), s[i].end(), m), m);
}
int ans[maxn];
int query(int c, int m)
{
int res = 0;
while (c > 0)
{
res += lower_bound(s[c].begin(), s[c].end(), m+1) - s[c].begin();
c -= c & -c;
}
return res-1;

}
int cnt[maxn];

int main()
{
#ifdef CraZYali
freopen("B.in", "r", stdin);
freopen("B.out", "w", stdout);
freopen("B.err", "w", stderr);
#endif
cin >> n >> k;
REP(i, 1, n)
{
int s(read<int>()), c(read<int>()), m(read<int>());
f[i] = flower(s, c, m, i);
}
sort(f + 1, f + 1 + n, cmp);
// REP(i, 1, n) printf("%d %d %d %d\n", f[i].s, f[i].c, f[i].m, f[i].id);

int last = 1;
REP(i, 1, n)
{
if (i > 1 && f[i].s ^ f[i-1].s)
{
REP(j, last, i-1)
cnt[ans[f[j].id] = query(f[j].c, f[j].m)]++;//, puts("----"), cerr << f[i].id << ' ' << ans[f[i].id] << endl;
last = i;
}
update(f[i].c, f[i].m);
}
REP(i, last, n) cnt[ans[f[i].id] = query(f[i].c, f[i].m)]++;//, puts("----"), cerr << f[i].id << ' ' << ans[f[i].id] << endl;
REP(i, 0, n-1) printf("%d\n", cnt[i]);
// REP(i, 1, n) fprintf(stderr, "%d\n", ans[i]);
return 0;
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×