cdq分治——bzoj1176: [Balkan2007]Mokia/bzoj2683: 简单题

http://hzwer.com/6002.html
网上题解么,代码全是一个样的,思路么,全都时很简单的讲讲;
唉;
这题目太明显了呀
i

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Ll long long
using namespace std;
struct cs{int x,y,v,num;bool k;}a[200005],c[200005];
struct toans{int to,k,v;}f[200005];
int F[2000005];
int ans[10005],top;
int n,x,y,z,v,m,xx,yy;
bool cmp2(cs a,cs b){return a.y<b.y;}
void init(int i,int v){for(;i<=m;i+=i&-i)F[i]+=v;}
void cle(int i){for(;i<=m;i+=i&-i)F[i]=0;}
int outit(int i){
    int ans=0;
    for(;i;i-=i&-i)ans+=F[i];
    return ans;
}
void cdq(int l,int r){
    if(l==r)return;
    int mid=l+r>>1;
    cdq(l,mid);
    for(int i=l;i<=r;i++)c[i]=a[i];
    sort(c+l,c+mid+1,cmp2);
    sort(c+mid+1,c+r+1,cmp2);
    int k=l-1;
    for(int i=mid+1;i<=r;i++)
        if(!c[i].k){
            while(k<mid&&c[k+1].y<=c[i].y)
                if(c[++k].k)
                    init(c[k].x,c[k].v);
            f[c[i].num].v+=outit(c[i].x);
        }
    for(int i=l;i<=mid;i++)if(c[i].k)cle(c[i].x);
    cdq(mid+1,r);
}
int main()
{
    scanf("%d%d",&m,&m);
    while(1){
        scanf("%d",&z);
        if(z==3)break;
        if(z==1){n++;scanf("%d%d%d",&a[n].x,&a[n].y,&a[n].v);a[n].k=1;}
        if(z==2){
            scanf("%d%d%d%d",&x,&y,&xx,&yy);
            top++;
            f[++n].to=top;f[n].k= 1;a[n].x=xx  ,a[n].y=yy  ;
            f[++n].to=top;f[n].k= 1;a[n].x=x-1 ,a[n].y=y-1 ;
            f[++n].to=top;f[n].k=-1;a[n].x=xx  ,a[n].y=y-1 ;
            f[++n].to=top;f[n].k=-1;a[n].x=x-1 ,a[n].y=yy  ;
        }
    }
    for(int i=1;i<=n;i++)a[i].num=i;
    cdq(1,n);
    for(int i=1;i<=n;i++)if(!a[i].k)ans[f[i].to]+=f[i].k*f[i].v;
    for(int i=1;i<=top;i++)printf("%d\n",ans[i]);
}

说来惭愧,矩形前缀和打错了,调了1h

双倍经验,爽
2683

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Ll long long
using namespace std;
struct cs{int x,y,v,num;bool k;}a[1000005],c[1000005];
struct toans{int to,k,v;}f[1000005];
int F[1000005];
int ans[1000005],top;
int n,x,y,z,v,m,xx,yy;
bool cmp2(cs a,cs b){return a.y<b.y;}
void init(int i,int v){for(;i<=m;i+=i&-i)F[i]+=v;}
void cle(int i){for(;i<=m;i+=i&-i)F[i]=0;}
int outit(int i){
    int ans=0;
    for(;i;i-=i&-i)ans+=F[i];
    return ans;
}
void cdq(int l,int r){
    if(l==r)return;
    int mid=l+r>>1;
    cdq(l,mid);
    for(int i=l;i<=r;i++)c[i]=a[i];
    sort(c+l,c+mid+1,cmp2);
    sort(c+mid+1,c+r+1,cmp2);
    int k=l-1;
    for(int i=mid+1;i<=r;i++)
        if(!c[i].k){
            while(k<mid&&c[k+1].y<=c[i].y)
                if(c[++k].k)
                    init(c[k].x,c[k].v);
            f[c[i].num].v+=outit(c[i].x);
        }
    for(int i=l;i<=mid;i++)if(c[i].k)cle(c[i].x);
    cdq(mid+1,r);
}
int main()
{
    scanf("%d",&m);
    while(1){
        scanf("%d",&z);
        if(z==3)break;
        if(z==1){n++;scanf("%d%d%d",&a[n].x,&a[n].y,&a[n].v);a[n].k=1;}
        if(z==2){
            scanf("%d%d%d%d",&x,&y,&xx,&yy);
            top++;
            f[++n].to=top;f[n].k= 1;a[n].x=xx  ,a[n].y=yy  ;
            f[++n].to=top;f[n].k= 1;a[n].x=x-1 ,a[n].y=y-1 ;
            f[++n].to=top;f[n].k=-1;a[n].x=xx  ,a[n].y=y-1 ;
            f[++n].to=top;f[n].k=-1;a[n].x=x-1 ,a[n].y=yy  ;
        }
    }
    for(int i=1;i<=n;i++)a[i].num=i;
    cdq(1,n);
    for(int i=1;i<=n;i++)if(!a[i].k)ans[f[i].to]+=f[i].k*f[i].v;
    for(int i=1;i<=top;i++)printf("%d\n",ans[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值