这题最恶心的地方在于去重
#include <bits/stdc++.h>
#define mid (l+r>>1)
using namespace std;
const int N=1e5+100;
struct node{
int a,b,c,id,num;
bool operator <(node x) const { //需要保证右区间对左区间一定没有贡献
if(a!=x.a) return a<x.a;
if(b!=x.b) return b<x.b;
if(c!=x.c) return c<x.c;
}
}s[N],tmp[N],s2[N];
int tree[2*N],f[N],tot,ans[N];
int lb(int x){
return x&-x;
}
void add(int x,int data){
while(x<=200000){
tree[x] += data;
x += lb(x);
}
}
int que(int x){
int ans = 0;
while(x>0){
ans += tree[x];
x -= lb(x);
}
return ans;
}
void cdq(int l,int r) {
if(l==r) return ;
cdq(l,mid);
cdq(mid+1,r);
int i = l;
int j = mid+1;
int tot = l-1; //此时a值左区间小于等于右区间,b值在两区间内升序
while(i <= mid&&j <= r) { //归并的过程中维护答案
if(s[i].b<=s[j].b) {
tmp[++tot] = s[i];
add(s[i].c,s[i].num);
i++;
}
else {
tmp[++tot] = s[j];
f[s[j].id] += que(s[j].c);
j++;
}
}
while(i <= mid) {
tmp[++tot] = s[i];
add(s[i].c,s[i].num);
i++;
}
while(j <= r){
tmp[++tot] = s[j];
f[s[j].id] += que(s[j].c);
j++;
}
for(int i = l; i <= mid; i++) add(s[i].c,-s[i].num); //还原树状数组
for(int i = l; i <= r; i++) s[i] = tmp[i];
}
int main(){
// freopen("a.txt","r",stdin);
ios::sync_with_stdio(0);
int n,k;
cin>>n>>k;
for(int i = 1; i <= n; i++) cin>>s2[i].a>>s2[i].b>>s2[i].c;
sort(s2+1,s2+n+1);
tot = 0;
for(int i = 1; i <= n; i++) { //去重
if(s2[i].a!=s2[i-1].a||s2[i].b!=s2[i-1].b||s2[i].c!=s2[i-1].c) {
s[++tot] = s2[i];
s[tot].id = tot;
s[tot].num = 1;
}
else
s[tot].num++;
}
cdq(1,tot);
sort(s+1,s+tot+1);
for(int i = 1; i <= tot; i++) {
f[i] += s[i].num-1; //重复元素造成的影响
ans[f[i]]+=s[i].num;
}
for(int i = 0; i < n; i++) cout<<ans[i]<<endl;
return 0;
}