CDQ分治
具体来看一个题:
陌上花开
题目描述
有 $ n $ 个元素,第 $ i $ 个元素有 $ a_i,b_i,c_i $ 三个属性,设 $ f(i) $ 表示满足 $ a_j \leq a_i $ 且 $ b_j \leq b_i $ 且 $ c_j \leq c_i $ 且 $ j \ne i $ 的 \(j\) 的数量.
对于 $ d \in [0, n) $,求 $ f(i) = d $ 的数量.
输入格式
第一行两个整数 $ n,k $,表示元素数量和最大属性值.
接下来 $ n $ 行,每行三个整数 $ a_i ,b_i,c_i $,分别表示三个属性值.
输出格式
$ n $ 行,第 $ d + 1 $ 行表示 $ f(i) = d $ 的 $ i $ 的数量.
样例
样例输入
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
样例输出
3
1
3
0
1
0
1
0
0
1
提示
$ 1 \leq n \leq 10^5$,$1 \leq a_i, b_i, c_i \le k \leq 2 \times 10^5 $.
对于三个数均小于当前数,我们可以使用CDQ分治来解决.
它的思想是,先按照第一维进行排序,再按照第二维进行分治,最后把第三维加入树状数组.
不想再详细写了,具体可以参考一下网上的详细解释.
给一个标程,具体里面有注释.
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 100001
#define rll rg ll
using namespace std;
struct node
{
ll a,b,c,num,ans;
}a[maxn],b[maxn];
inline bool cmp_a(node a,node b)
{
if(a.a==b.a)
{
if(a.b==b.b) return a.c<b.c;
return a.b<b.b;
}
return a.a<b.a;
}
inline bool cmp_b(node a,node b)
{
if(a.b==b.b)
{
if(a.a==b.a) return a.c<b.c;
return a.a<b.a;
}
return a.b<b.b;
}
ll cnt;
ll n,k;
ll ans[maxn];
ll c[maxn];//树状数组
#define lowbit(x) (x&-x)
inline void add(ll x,ll y)
{
for(rll i=x;i<=k;i+=lowbit(i))
c[i]+=y;
}
inline ll query(ll x)
{
rll ans=0;
for(rll i=x;i;i-=lowbit(i))
ans+=c[i];
return ans;
}
inline void cdqfz(ll l,ll r)
{
if(l==r) return;
rll mid=(l+r)>>1;
cdqfz(l,mid);
cdqfz(mid+1,r);
sort(b+l,b+mid+1,cmp_b);//[l,mid+1)=[l,mid]
sort(b+mid+1,b+r+1,cmp_b);//[mid+1,r+1)=[mid+1,r]
rll tmp=l;
for(rll i=mid+1;i<=r;i++)
{
while(b[i].b>=b[tmp].b&&tmp<=mid)
add(b[tmp].c,b[tmp].num),tmp++;
b[i].ans+=query(b[i].c);//求严格小于它的个数
}
for(rll i=l;i<=tmp-1;i++) add(b[i].c,-b[i].num);
//清空操作
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>k;
for(rll i=1;i<=n;i++) cin>>a[i].a>>a[i].b>>a[i].c;
sort(a+1,a+n+1,cmp_a);
for(rll i=1,num=0;i<=n;i++)
{
num++;//相同的项的个数
if(a[i].a!=a[i+1].a||a[i].b!=a[i+1].b||a[i].c!=a[i+1].c)
b[++cnt]=a[i],b[cnt].num=num,num=0;
}
cdqfz(1,cnt);
for(rll i=1;i<=cnt;i++)
ans[b[i].ans+b[i].num]+=b[i].num;
for(rll i=1;i<=n;i++) cout<<ans[i]<<endl;
return 0;
}
--END--

浙公网安备 33010602011771号
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/articles/16388050.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!