【BZOJ】【P3262】【陌上花开】【题解】【树套树】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3262

今天原本打算学一下cdq分治的……

就找了几道模板题

然后发现全都可以树套树……

唉……树套树就树套树吧


三维偏序

一维排序

二维树状数组

三维平衡树

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,k,size;
struct tup{
	int x,y,z,s;
	tup(int _x=0,int _y=0,int _z=0,int _s=0):x(_x),y(_y),z(_z),s(_s){}
	bool operator<(tup oth)const{
		return x==oth.x?y==oth.y?z<oth.z:y<oth.y:x<oth.x;
	}
	bool operator==(tup oth)const{return x==oth.x&&y==oth.y&&z==oth.z;}
	bool operator!=(tup oth)const{return !(*this==oth);}
}a[maxn],b[maxn];
struct node{  
    int val,key,sum,s;  
    node *c[2];  
    node(int _val=0,int _s=0,node *C=0){  
        val=_val;key=rand();sum=s=_s;  
        c[0]=c[1]=C;  
    }  
    void rz(){  
        sum=c[0]->sum+s+c[1]->sum;  
    }  
}pool[maxn],*Null;  
node *newnode(int _val=0,int _s=0,node *C=0){  
    static int tot=0;  
    if(tot<maxn){  
        pool[tot].val=_val;  
        pool[tot].key=rand();  
        pool[tot].sum=pool[tot].s=_s;  
        pool[tot].c[0]=pool[tot].c[1]=C;  
        return &pool[tot++];  
    }else return new node(_val,_s,C);  
}  
struct Treap{  
    node *root;  
    void init(){  
        root=Null;  
    }  
    void rot(node *&t,bool d){  
        node *p=t->c[d];t->c[d]=p->c[!d];  
        p->c[!d]=t;t->rz();p->rz();t=p;  
    }  
    void insert(node *&t,int val,int s){  
        if(t==Null){t=newnode(val,s,Null);return;}  
        if(t->val==val){t->s+=s;t->sum+=s;return;}  
        bool d=t->val<val;  
        insert(t->c[d],val,s);  
        if(t->c[d]->key<t->key)rot(t,d);  
        else t->rz();  
    }  
    int Qsum(node *t,int x){  
        int ans=0;  
        while(t!=Null){  
            if(t->val<=x)ans+=t->c[0]->sum+t->s,t=t->c[1];  
            else t=t->c[0];  
        }return ans;  
    }  
    void insert(int val,int s){insert(root,val,s);}  
    int Qsum(int l,int r){return Qsum(root,r)-Qsum(root,l-1);}  
};  
Treap d[maxn<<1];
inline int lowbit(int x){return x&-x;}
void updata(int x,int y,int z){
	while(x<=k)d[x].insert(y,z),x+=lowbit(x);
}
int get(int x,int y){
	int ans=0;
	while(x)ans+=d[x].Qsum(1,y),x-=lowbit(x);
	return ans;
}
int anss[maxn];
int getint(){
	int res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res;
}
int main(){
	Null=newnode(INT_MAX,0,0);  
    Null->key=INT_MAX;Null->c[0]=Null->c[1]=Null;  
	n=getint();k=getint();
	for(int i=1;i<=k;i++)d[i].init();
	for(int i=1;i<=n;i++)a[i].x=getint(),a[i].y=getint(),a[i].z=getint();
	sort(a+1,a+1+n);
	for(int i=1;i<=n;++i)
		if(a[i]!=a[i-1])
			b[++size]=a[i],b[size].s++;
		else b[size].s++;		
	for(int i=1;i<=size;i++){
		int ans=get(b[i].y,b[i].z);
		anss[ans+b[i].s-1]+=b[i].s;
		updata(b[i].y,b[i].z,b[i].s);
	}for(int i=0;i<n;i++)printf("%d\n",anss[i]);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值