cdq入门
作者:互联网
cdq不是一个具体的算法,它是一种思想。cdq之于分治,就像区间dp之于dp。
三维偏序
模板题
思路,先考虑二维。排序使第一维有序,然后顺序遍历,第二位用树状数组维护。
如果把顺序遍历,改成如归并排序的方式,题目仍然可行,但多了一个logn。
三维情况下,就可以先排序使第一维有序,再向下递归。向上合并时保证第二维有序,每次合并时用树状数组维护第三维即可。
据说cdq还能处理四维偏序,但暂时还不会
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=2e5+100;
template<typename T>
inline void read(T &x){
x=0;T fl=1;char tmp=getchar();
while(tmp<'0'||tmp>'9')fl=tmp=='-'?-fl:fl,tmp=getchar();
while(tmp>='0'&&tmp<='9')x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
x=x*fl;
}
int n,k;
struct node{
int a,b,c,id;
}p[maxn];
int t[maxn],f[maxn];
inline int lowbit(const int x){return x&-x;}
inline void add(int x){
while(x<=k){
t[x]++;
x+=lowbit(x);
}
}
inline void mns(int x){
while(x<=k){
t[x]--;
x+=lowbit(x);
}
}
inline int ask(int x){
int ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
bool cmp_a(const node x,const node y){
if(x.a!=y.a)return x.a<y.a;
if(x.b!=y.b)return x.b<y.b;
if(x.c!=y.c)return x.c<y.c;
return x.id<y.id;
}
bool cmp_b(const node x,const node y){
if(x.b!=y.b)return x.b<y.b;
if(x.c!=y.c)return x.c<y.c;
return x.id<y.id;
}
bool cmp(const node x,const node y){
return x.id<y.id;
}
void solve(int l,int r){
if(l==r)return ;
int mid=l+r>>1;
solve(l,mid),solve(mid+1,r);
int i=mid+1,j=l;
while(i<=r){
while(p[j].b<=p[i].b&&j<=mid)add(p[j].c),j++;
f[p[i].id]+=ask(p[i].c),i++;
}
for(int i=l;i<j;i++)
mns(p[i].c);
sort(p+l,p+r+1,cmp_b);
}
int cnt[maxn];
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++)
read(p[i].a),read(p[i].b),read(p[i].c),p[i].id=i;
sort(p+1,p+n+1,cmp_a);
solve(1,n);
sort(p+1,p+n+1,cmp_a);
for(int i=n-1;i>=1;i--)
if(p[i].a==p[i+1].a&&p[i].b==p[i+1].b&&p[i].c==p[i+1].c)
f[p[i].id]=f[p[i+1].id];
for(int i=1;i<=n;i++)
cnt[f[i]]++;
for(int i=0;i<n;i++)
printf("%d\n",cnt[i]);
// for(int i=1;i<=n;i++)
// printf("%d\n",f[i]);
return 0;
}
标签:tmp,入门,int,while,cdq,&&,fl 来源: https://www.cnblogs.com/xyc1719/p/16560238.html