AcWing2847 老C的任务(CDQ分治)

计算二维前缀和,更新一下归并的板子

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
struct node{
    int x,y,z,p,id,sign;
    ll sum;
    bool operator <(const node & t)const{
        if(x!=t.x)
            return x<t.x;
        if(y!=t.y)
            return y<t.y;
        return z<t.z;
    }
}q[N],w[N];
int cnt=0;
ll ans[N];
void cdq(int l,int r){
    if (l >= r) return;
    int mid=l+r>> 1;
    cdq(l, mid);
    cdq(mid + 1, r);
    int i=l, j=mid+1,k = 0;
    ll sum=0;
    while(i<=mid&&j<=r)
        if(q[i].y<=q[j].y) sum+=!q[i].z*q[i].p,w[k++]=q[i ++ ];
        else q[j].sum+=sum, w[k ++ ] = q[j ++ ];
    while (i<=mid) sum+=!q[i].z*q[i].p,w[k++]=q[i ++ ];
    while (j<=r) q[j].sum+=sum,w[k ++ ]=q[j ++ ];
    for(i=l,j=0; j<k;i++,j++) q[i]=w[j];
}
int main(){
    ios::sync_with_stdio(false);
    int n,m;
    cin>>n>>m;
    int i,j;
    for(i=1;i<=n;i++){
        int a,b,c;
        cin>>a>>b>>c;
        q[++cnt]={a,b,0,c};
    }
    for(i=1;i<=m;i++){
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        q[++cnt]={x1-1,y1-1,1,0,i,1};
        q[++cnt]={x2,y2,1,0,i,1};
        q[++cnt]={x1-1,y2,1,0,i,-1};
        q[++cnt]={x2,y1-1,1,0,i,-1};
    }
    sort(q+1,q+1+cnt);
    cdq(1,cnt);
    for(i=1;i<=cnt;i++){
        if(q[i].z){
            ans[q[i].id]+=q[i].sum*q[i].sign;
        }
    }
    for(i=1;i<=m;i++){
        cout<<ans[i]<<endl;
    }
}
View Code

 

posted @ 2020-12-12 16:25  朝暮不思  阅读(82)  评论(0编辑  收藏  举报