[COGS 577] 蝗災

描述

一個方陣,支持單點修改,查詢一個小矩陣的和。

思路

蒟蒻並不會樹套樹,但最近學了點CDQ分治的皮毛,做了一下這道題。
對於修改直接記錄。
對於查詢拆成四部分。

類似於矩陣前綴和,運用查分的思想。
ans=1+2-3-4;
然後cdq中維護x升序。以y爲下標維護樹狀數組。
記錄左區間修改,修改右區間的查詢。

代碼

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=1000000+10;
struct node
{
    int val,type,tag,x,y;
    bool operator < (const node &o) const
    {
        if(x!=o.x) return x<o.x;
        else if(y!=o.y) return y<o.y;
        else return type<o.type;
    }
}a[maxn],b[maxn],tt[maxn];
int n,m,tot,totx,ans[maxn];
int tree[maxn];
int lowbit(int x)
{
    return x&(-x);
}
void modify(int x,int d)
{
    while(x<=n)
    {
        tree[x]+=d;
        x+=lowbit(x);
    }
}
int query(int x)
{
    int ans=0;
    while(x)
    {
        ans+=tree[x];
        x-=lowbit(x);
    }
    return ans;
}
void cdq(int l,int r)
{
    if(l==r) return;
    int mid=(l+r)>>1;
    cdq(l,mid); cdq(mid+1,r);
    int p1=l,p2=mid+1,cnt=0;
    for(int i=l; i<=r; i++)
    {
        if((p1<=mid && a[p1]<a[p2]) || p2>r)
        {
            if(a[p1].type==1)
            {
                cnt++; tt[cnt]=a[p1]; modify(a[p1].y,a[p1].val);
            }
            b[i]=a[p1]; p1++;
        }
        else
        {
            if(a[p2].type==2)
            {
                ans[a[p2].val]+=a[p2].tag*query(a[p2].y);
            }
            b[i]=a[p2]; p2++;
        }
    }
    for(int i=l; i<=r; i++) a[i]=b[i];
    for(int i=1; i<=cnt; i++)
    {
        modify(tt[i].y,-tt[i].val);
    }
}
int main()
{
    freopen("locust.in","r",stdin);
    freopen("locust.out","w",stdout);
    scanf("%d %d",&n,&m);
    while(m--)
    {
        int opt;
        scanf("%d",&opt);
        if(opt==1)
        {
            int x,y,w; scanf("%d %d %d",&x,&y,&w);
            tot++; a[tot].type=1; a[tot].x=x; a[tot].y=y;
            a[tot].val=w;
        }
        else
        {
            int xx,yy,x2,y2; totx++;
            scanf("%d %d %d %d",&xx,&yy,&x2,&y2);
            //拆成四部分,建議畫一下圖
            tot++; a[tot]=(node){totx,2,1,x2,y2};
            tot++; a[tot]=(node){totx,2,1,xx-1,yy-1};
            tot++; a[tot]=(node){totx,2,-1,xx-1,y2};
            tot++; a[tot]=(node){totx,2,-1,x2,yy-1};
        }
    }
    cdq(1,tot);
    for(int i=1; i<=totx; i++)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章