1. 程式人生 > 實用技巧 >AcWing2847 老C的任務(CDQ分治)

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