三维偏序(陌上花开) CDQ分治

本文深入探讨了使用树状数组优化算法效率的方法,通过具体案例展示了如何在大规模数据集上进行快速查询和更新操作,特别关注了算法的时间复杂度和空间优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

十分巧妙。

Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 200000
#define N 3000000
#define ll long long
using namespace std;
int k,n;
int C[N],ans[maxn],cnt[maxn];  
int lowbit(int x){ return x&(-x); }
void add(int pos,int x){
    while(pos<=k) C[pos]+=x,pos+=lowbit(pos); 
}
int query(int pos){
    int sum=0;
    while(pos>0) sum+=C[pos],pos-=lowbit(pos); 
    return sum; 
}
struct OPT{
    int x,y,z,w,idx; 
}arr[maxn],opt[maxn]; 
int cmpx(OPT a,OPT b){ return (a.x==b.x&&a.y==b.y)?(a.z<b.z):((a.x==b.x)?a.y<b.y:a.x<b.x); }
int cmpy(OPT a,OPT b){ return (a.y==b.y)?a.z<b.z:a.y<b.y; }
void solve(int l,int r){
    if(l>=r) return;
    int mid=(l+r)>>1;
    solve(l,mid),solve(mid+1,r);
    sort(opt+l,opt+mid+1,cmpy),sort(opt+mid+1,opt+r+1,cmpy);
    int p=l,q=mid+1;
    for(;q<=r;++q){
        while(opt[p].y<=opt[q].y&&p<=mid) add(opt[p].z,opt[p].w),++p; 
        ans[opt[q].idx]+=query(opt[q].z); 
    }
    for(int i=l;i<p;++i) add(opt[i].z,-opt[i].w); 
}
int main()
{
    //setIO("input"); 
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i)scanf("%d%d%d",&arr[i].x,&arr[i].y,&arr[i].z);
    sort(arr+1,arr+1+n,cmpx);
    int u=n,cc=0; 
    n=0; 
    for(int i=1;i<=u;++i){
        ++cc;
        if(arr[i].x!=arr[i+1].x||arr[i].y!=arr[i+1].y||arr[i].z!=arr[i+1].z) 
            opt[++n]=arr[i],opt[n].w=cc,opt[n].idx=n,cc=0; 
    }
    solve(1,n); 
    for(int i=1;i<=n;i++)
        cnt[ans[opt[i].idx]+opt[i].w-1]+=opt[i].w;
    for(int i=0;i<u;++i) printf("%d\n",cnt[i]); 
    return 0; 
}

  

转载于:https://www.cnblogs.com/guangheli/p/10259786.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值