bzoj3262 陌上花开

传送门

首先按照 a a a排序。在分治的时候就没有第一维的影响了。
然后分治的时候两个区间分别按照第二维排序。记左右两个指针。
右边指针一个一个向右跳,左边指针移到第二维小等于右边指针的最大位置。并且在左指针跳的时候把对应的 c c c记入权值树状数组里面。左指针跳完之后用右边的 c c c查一查前缀和即可。

分治完之后要把影响消掉。
树状数组要开权值大小。
并且要去重。因为相同的之间是相互大于。

#include<bits/stdc++.h>
#define re register
#define cs const
#define lowbit(x) (x&(-x))
#define mid (l+r>>1)
cs int N=1e5+10,K=2e5+10;
int n,k,tot,tr[K],ans[N];
namespace IO{
	cs int Rlen=1<<22|1;
	char buf[Rlen],*p1,*p2;
	inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
	template<typename T>
	inline T get(){
		char ch;T x;
		while(!isdigit(ch=gc()));x=ch^48;
		while(isdigit(ch=gc())) x=((x+(x<<2))<<1)+(ch^48);
		return x;
	}
	inline int gi(){return get<int>();}
}
using IO::gi;
struct node{int a,b,c,cnt,num;}a[N];
inline bool comp_all(cs node &a,cs node &b){
	if(a.a!=b.a) return a.a<b.a;
	if(a.b!=b.b) return a.b<b.b;
	return a.c<b.c;
}
inline bool comp_b(cs node &a,cs node &b){
	if(a.b!=b.b) return a.b<b.b;
	return a.c<b.c;
}
inline bool operator!=(cs node &a,cs node &b){
	return (a.a!=b.a)||(a.b!=b.b)||(a.c!=b.c);
}
inline void add(int x,int v){for(;x<=k;x+=lowbit(x)) tr[x]+=v;}
inline int query(int x,int ret=0){for(;x;x-=lowbit(x)) ret+=tr[x];return ret;}
void solve(int l,int r){
	if(l==r) return;
	solve(l,mid),solve(mid+1,r);
	std::sort(a+l,a+mid+1,comp_b);
	std::sort(a+mid+1,a+r+1,comp_b);
	int pl=l;
	for(int pr=mid+1;pr<=r;++pr){
		while(pl<=mid&&a[pl].b<=a[pr].b)
			add(a[pl].c,a[pl].cnt),++pl;
		a[pr].num+=query(a[pr].c);
	}while(--pl>=l) add(a[pl].c,-a[pl].cnt);
}
int main(){
//	freopen("3131.in","r",stdin);
	n=gi(),k=gi();
	for(int re i=1;i<=n;++i) a[i].a=gi(),a[i].b=gi(),a[i].c=gi();
	std::sort(a+1,a+n+1,comp_all);
	for(int re i=1,t=1;i<=n;++i,++t)
		if(a[i]!=a[i+1]) a[++tot]=a[i],a[tot].cnt=t,t=0;
	solve(1,tot);
	for(int re i=1;i<=tot;++i) ans[a[i].num+a[i].cnt-1]+=a[i].cnt;
	for(int re i=0;i< n;++i) printf("%d\n",ans[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值