Magnificent Tree - 牛客网

https://www.nowcoder.com/acm/contest/106/H

分治就是讲大问题划分成许多小问题 也就是把1到num这些操作序列 划分成许多小序列 对每个[l,r]的小序列 考虑l,m]这个小序列对[m+1,r]这个序列的影响 在这里即是看左子序列的修改会对右子序列造成什么影响

对每个子问题 右区间的查询序要关心的是左区间当中在自己坐标范围内的修改 以x或y两者中的一个建立顺序关系 然后用线段树维护另一个 这样就将一个二维线段树的问题在空间复杂度上降了整整一维

当然动态主席树也可以 但是空间吃不消 代码略

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=5e5+10;
  
struct node
{
    int tp,x,y,val;
};
  
node order[maxm],tmp[maxm];
int sum[maxn],ans[maxn];
int n,q,tot,cnt;
  
int lowbit(int x)
{
    return x&(-x);
}
  
void update(int tar,int val)
{
    int i;
    for(i=tar;i<=n;i+=lowbit(i)) sum[i]+=val;
}
  
int query(int tar)
{
    int res,i;
    res=0;
    for(i=tar;i>=1;i-=lowbit(i)) res+=sum[i];
    return res;
}
  
void cdq(int l,int r)
{
    int m,i,p,q,pos;
    if(l==r) return;
    m=(l+r)/2;
    cdq(l,m),cdq(m+1,r);
    pos=l,p=l,q=m+1;
    while(p<=m&&q<=r){
        if(order[p].x<=order[q].x){
            if(order[p].tp==1) update(order[p].y,order[p].val);
            tmp[pos++]=order[p++];
        }
        else{
            if(order[q].tp==2) ans[order[q].val]-=query(order[q].y);
            else if(order[q].tp==3) ans[order[q].val]+=query(order[q].y);
            tmp[pos++]=order[q++];
        }
    }
    while(q<=r){
        if(order[q].tp==2) ans[order[q].val]-=query(order[q].y);
        else if(order[q].tp==3) ans[order[q].val]+=query(order[q].y);
        tmp[pos++]=order[q++];
    }
    for(i=l;i<=p-1;i++){
        if(order[i].tp==1) update(order[i].y,-order[i].val);
    }
    while(p<=m) tmp[pos++]=order[p++];
    for(i=l;i<=r;i++) order[i]=tmp[i];
}
  
int main()
{
    int i,tp,x1,y1,x2,y2,h;
    scanf("%d%d",&q,&n);
    for(i=1;i<=q;i++){
        scanf("%d",&tp);
        if(tp==1){
            scanf("%d%d%d",&x1,&y1,&h);
            order[++tot].tp=1,order[tot].x=x1,order[tot].y=y1,order[tot].val=h;
        }
        else{
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            cnt++;
            if(x1-1>=1) order[++tot].tp=2,order[tot].x=x1-1,order[tot].y=y2,order[tot].val=cnt;
            if(y1-1>=1) order[++tot].tp=2,order[tot].x=x2,order[tot].y=y1-1,order[tot].val=cnt;
            if(x1-1>=1&&y1-1>=1) order[++tot].tp=3,order[tot].x=x1-1,order[tot].y=y1-1,order[tot].val=cnt;
            order[++tot].tp=3,order[tot].x=x2,order[tot].y=y2,order[tot].val=cnt;
        }
    }
    cdq(1,tot);
    for(i=1;i<=cnt;i++) printf("%d\n",ans[i]);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值