#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
inline int read(){
char ch=getchar();
int fh=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')fh=(fh<<3)+(fh<<1)+(ch^48),ch=getchar();
return fh;
}
struct node{
int a,b,c,cnt,ans;
}e[N],f[N];
int n,k,answ[N],cf,m;
class tree_bl{
public:
inline void set(int many,int fjlvm){how_many=many;tree=new int[fjlvm];}
//set数的个数以及树状数组大小
inline void add_wh(int node,int data){while(node<=how_many){tree[node]+=data;node+=lowbit(node);}}
//while的修改
inline void add_dg(int node,int data){if(node>how_many)return ;tree[node]+=data;add_dg(node+lowbit(node),data);}
//递归的修改
inline void add_fo(int node,int data){for(;node<=how_many;node+=lowbit(node))tree[node]+=data;}
//for的修改
inline int ask(int what){int fh=0;while(what){fh+=tree[what];what=what-lowbit(what);}return fh;}
//查询
#define add add_wh
inline void delete_tree(void){delete[] tree;}
//删除树状数组
friend void debug_tree(tree_bl &shuzu);
//输出树状数组内数字
private:
int how_many;
int *tree;
inline int lowbit(int X){return X&(-X);}
};
void debug_tree(tree_bl &shuzu){
putchar('\n');
for(int i=0;i<=shuzu.how_many;i=-~i)std::cout<<shuzu.tree[i]<<'\n';
putchar('\n');
}
tree_bl tr;//建立树状数组
inline bool cmp1(node ldr,node zc){
return ldr.a==zc.a?(ldr.b==zc.b?ldr.c<zc.c:ldr.b<zc.b):ldr.a<zc.a;
}
inline bool cmp2(node ldr,node zc){
return ldr.b==zc.b?ldr.c<zc.c:ldr.b<zc.b;
}
void cdq(int l,int r){
if(l==r)return ;
int mid=(l+r)>>1;
cdq(l,mid),cdq(mid+1,r);//向下二分
sort(f+l,f+mid+1,cmp2),sort(f+mid+1,f+r+1,cmp2);
//排序合并下面两个区间,计算相互影响
int j=l;//j从l~mid,i从mid+1~r
for(int i=mid+1;i<=r;i=-~i){
while(f[i].b>=f[j].b&&j<=mid){
tr.add(f[j].c,f[j].cnt);
++j;
}
f[i].ans+=tr.ask(f[i].c);//判断是否符合
}//类似归并排序
for(int i=l;i<j;i=-~i)tr.add(f[i].c,-f[i].cnt);//删除结点
}
int main(){
n=read(),k=read();
for(int i=1;i<=n;i=-~i)e[i].a=read(),e[i].b=read(),e[i].c=read();
sort(e+1,e+1+n,cmp1);
//将三维偏序问题转换为二维,此时aj<=ai的限制条件已然失效
//j<mid i>mid 此时j<i,aj必然小于ai
for(int i=1;i<=n;i=-~i){
++cf;
if(e[i].a!=e[i+1].a||e[i].b!=e[i+1].b||e[i].c!=e[i+1].c){
++m;
f[m].a=e[i].a;
f[m].b=e[i].b;
f[m].c=e[i].c;
f[m].cnt=cf;
cf=0;
}
}
//去重转换到f数组进行cdq
//因为此题要考虑等于的情况,而原版CDQ只考虑严格大于/小于情况
//可以手模一下就知道不去重不行
tr.set(m,N);
cdq(1,m);
for(int i=1;i<=m;i=-~i)answ[f[i].ans+f[i].cnt-1]+=f[i].cnt;
for(int i=1;i<=n;i=-~i)printf("%d\n",answ[i-1]);
}
思路是题解的第一篇,我们教练让我们自己学习给大家分享,所以代码有详细解释