这道题应该是学CDQ分治的必做题也是CDQ分治一个很好的运用 三维偏序问题
题意是给你
n
n
个三元组 对于每个三元组
i
i
统计满足的
j
j
的个数
对于第一维的限制 我们可以直接 解决, 第二维我们可以用CDQ分治来进行计算, 最后再把满足第三维条件的数加入到树状数组即可 复杂度 O(nlog2n) O ( n l o g 2 n ) 具体实现见代码
notice:
n
o
t
i
c
e
:
树状数组每次分治使用完一定要清空, 并且要记得对三元组进行去重.
题目链接
#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define mid ((l + r) >> 1)
using namespace std;
const int maxn = 2e5 + 10;
int n, k, ans[maxn], vis[maxn], m;
struct node
{
int x, y, z, rk;
bool operator < (const node T)
{
if(x == T.x && y == T.y)
return z < T.z;
if(x == T.x)
return y < T.y;
return x < T.x;
}
}A[maxn], tmp[maxn];
namespace Fenwick_Tree
{
int s[maxn];
int lowbit(int x)
{
return x & -x;
}
void update(int x, int y)
{
while(x <= k)
{
s[x] += y;
x += lowbit(x);
}
}
int query(int x)
{
int res = 0;
while(x)
{
res += s[x];
x -= lowbit(x);
}
return res;
}
}
void CDQ(int l, int r)
{
if(l != r)
{
CDQ(l, mid), CDQ(mid + 1, r);
int t = l, t1 = l, t2 = mid + 1;
while(t1 <= mid && t2 <= r)
{
if(A[t1].y <= A[t2].y)
{
Fenwick_Tree::update(A[t1].z, 1);
vis[t] = 1;
tmp[t ++] = A[t1 ++];
}
else
{
A[t2].rk += Fenwick_Tree::query(A[t2].z);
tmp[t ++] = A[t2 ++];
}
}
while(t1 <= mid)
tmp[t ++] = A[t1 ++];
while(t2 <= r)
{
A[t2].rk += Fenwick_Tree::query(A[t2].z);
tmp[t ++] = A[t2 ++];
}
For(i, l, r)
{
A[i] = tmp[i];
if(vis[i])
{
vis[i] = 0;
Fenwick_Tree::update(A[i].z, -1);
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("3262.in", "r", stdin);
freopen("3262.out", "w", stdout);
#endif
scanf("%d%d", &n, &k);
For(i, 1, n)
scanf("%d%d%d", &A[i].x, &A[i].y, &A[i].z);
sort(A + 1, A + n + 1);
CDQ(1, n);
for(int i = n; i >= 1; -- i)
if(A[i].x == A[i - 1].x && A[i].y == A[i - 1].y && A[i].z == A[i - 1].z)
A[i - 1].rk = A[i].rk;
For(i, 1, n)
++ ans[A[i].rk];
For(i, 0, n - 1)
printf("%d\n", ans[i]);
return 0;
}