分析
CDQ板子,用树状数组实时维护,分治完后要恢复树状数组
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int N=100101;
int n,m,ans[N],k,a[N],b[N],c[N],rk[N],qk[N],w[N],cnt[N],h[N<<1];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline bool cmp(int x,int y){return a[x]<a[y]||(a[x]==a[y]&&(b[x]<b[y]||(b[x]==b[y]&&c[x]<c[y])));}
inline void update(int x,int y){for (;x<=k;x+=-x&x) h[x]+=y;}
inline signed answ(int x){rr int ans=0; for (;x;x-=-x&x) ans+=h[x]; return ans;}
inline void cdq(int *rk,int n){
if (n==1) return;
rr int mid=n>>1,i,j,k;
cdq(rk,mid),cdq(rk+mid,n-mid);
memcpy(qk,rk,n<<2);
for (k=i=0,j=mid;i<mid&&j<n;++k){
rr int x=qk[i],y=qk[j];
if (b[x]<=b[y]) update(c[rk[k]=x],w[x]),++i;
else cnt[y]+=answ(c[rk[k]=y]),++j;
}
for (;j<n;++j) cnt[qk[j]]+=answ(c[qk[j]]);
memcpy(rk+k,qk+i,(mid-i)<<2);
for (--i;~i;--i) update(c[qk[i]],-w[qk[i]]);
}
signed main(){
m=iut(); k=iut();
for (rr int i=0;i<m;++i) rk[i]=i,a[i]=iut(),b[i]=iut(),c[i]=iut();
sort(rk,rk+m,cmp);
for (rr int i=1;i<m;++i){
rr int x=rk[i],y=rk[n]; ++w[y];
if ((a[x]^a[y])||(b[x]^b[y])||(c[x]^c[y])) rk[++n]=x;
}
++w[rk[n]],++n; cdq(rk,n);
for (rr int i=0;i<n;++i) ans[cnt[rk[i]]+w[rk[i]]-1]+=w[rk[i]];
for (rr int i=0;i<m;++i) print(ans[i]),putchar(10);
return 0;
}