题目链接:https://www.luogu.com.cn/problem/P3810
线段树套线段树
#include<bits/stdc++.h>
#define ls lc[o]
#define rs rc[o]
#define mid (l+r)/2
using namespace std;
typedef long long ll;
const int NN=100100;
const int inf=0x3f3f3f3f;
ll n,m,k,x,y,z,q,W,T,N,cnt,tmp,dst,cas,val,tot,num;
int c[NN*80],lc[NN*80],rc[NN*80],rot[NN*2],ans[NN];
struct node{
int x,y,z;
bool operator <(const node nod)const{
return (x==nod.x?(y==nod.y?z<nod.z:y<nod.y):x<nod.x);
}
bool operator !=(const node nod)const{
return x!=nod.x||y!=nod.y||z!=nod.z;
}
void input(){
cin>>x>>y>>z;
}
};
node a[NN];
//动态开点,其实没那么难,不要被吓到了
void update(int l,int r,int pos,int &o){
if(!o) o=++tot;
c[o]++;
if(l==r) return ;
if(mid>=pos) update(l,mid,pos,ls);
else update(mid+1,r,pos,rs);
}
void update(int i,int val){
while(i<=k){
//对权值树状数组的每一个权值维护一个动态开点的权值线段树
update(1,k,val,rot[i]);
i+=i&-i;
}
}
ll query(int l,int r,int pos,int o){
if(r<=pos||c[o]==0) return c[o];
ll sum=0;
sum+=query(l,mid,pos,ls);
if(mid<pos) sum+=query(mid+1,r,pos,rs);
return sum;
}
ll getnum(int i,int val){
ll sum=0;
while(i){
sum+=query(1,k,val,rot[i]);
i-=i&-i;
}
return sum;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++) a[i].input();
sort(a+1,a+n+1);
int cnt=1;
for(int i=1;i<=n;i++){
update(a[i].y,a[i].z);
if(a[i]!=a[i+1]) ans[getnum(a[i].y,a[i].z)]+=cnt,cnt=1;
else cnt++;
}
for(int i=1;i<=n;i++) cout<<ans[i]<<endl;
}