HDU 1892 See you~ 解题报告(线段树版)

  A了一晚上。。。

  题目看起来就是个线段树,不过是平面的。仍然是二分的思想,我们可以每次横向分,纵向分,即4分。二维线段树吧

  贴代码:

#include <iostream>
using namespace std;

#define rect 0,1000,0,1000,1,1
#define defhm int hm=(l+r)>>1;
#define defvm int vm=(t+b)>>1;
#define ltson l,hm,t,vm,pos<<1,posy<<1
#define rtson hm+1,r,t,vm,pos<<1|1,posy<<1
#define lbson l,hm,vm+1,b,pos<<1,posy<<1|1
#define rbson hm+1,r,vm+1,b,pos<<1|1,posy<<1|1

int old;
bool overflow;
const int maxn=1111;
int sum[maxn<<2][maxn<<2];

void updateFather(int pos,int posy)
{
    sum[pos][posy]=sum[pos<<1][posy<<1]+sum[pos<<1|1][posy<<1]+sum[pos<<1][posy<<1|1]+sum[pos<<1|1][posy<<1|1];
}

void build(int l,int r,int t,int b,int pos,int posy)
{
    if(l==r && t==b)
    {
        sum[pos][posy]=1;
        return;
    }
    defvm;
    defhm;
    if(l<r && t<b)
    {
        build(ltson);
        build(rtson);
        build(lbson);
        build(rbson);
    }
    else if(l<r && t==b)
    {
        build(ltson);
        build(rtson);
    }
    else if(t<b && l==r)
    {
        build(ltson);
        build(lbson);
    }
    updateFather(pos,posy);
}

void update(int px,int py,int add,int l,int r,int t,int b,int pos,int posy)
{
    if(l==r && t==b)
    {
        old=sum[pos][posy];
        sum[pos][posy]+=add;
        if(sum[pos][posy]<0)
        {
            overflow=true;
            sum[pos][posy]=0;
        }
        return;
    }
    defhm;
    defvm;
    if(px<=hm && py<=vm)
        update(px,py,add,ltson);
    if(px<=hm && vm<py)
        update(px,py,add,lbson);
    if(hm<px && py<=vm)
        update(px,py,add,rtson);
    if(hm<px && vm<py)
        update(px,py,add,rbson);
    updateFather(pos,posy);
}

int query(int L,int R,int T,int B,int l,int r,int t,int b,int pos,int posy)
{
    if(L<=l&&r<=R&&T<=t&&b<=B)
    {
        return sum[pos][posy];
    }
    defhm;
    defvm;
    int SUM=0;
    if(L<=hm && T<=vm)
        SUM+=query(L,R,T,B,ltson);
    if(L<=hm && vm<B)
        SUM+=query(L,R,T,B,lbson);
    if(hm<R && T<=vm)
        SUM+=query(L,R,T,B,rtson);
    if(hm<R && vm<B)
        SUM+=query(L,R,T,B,rbson);
    return SUM;
}

int main()
{
    int T,cas,n;
    char str[10];
    int x1,x2,y1,y2,add;
    scanf("%d",&cas);
    for(T=1;T<=cas;T++)
    {
        printf("Case %d:\n",T);
        build(rect);

        scanf("%d",&n);
        while(n--)
        {
            scanf("%s",str);
            if(str[0]=='A' || str[0]=='D')
            {
                scanf("%d%d%d",&x1,&y1,&add);
                update(x1,y1,add*(str[0]=='A'?1:-1),rect);
            }
            else if(str[0]=='M')
            {
                overflow=false;
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&add);
                update(x1,y1,-add,rect);
                if(overflow)
                    add=old;
                update(x2,y2,add,rect);
            }
            else
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                if(x1>x2) swap(x1,x2);
                if(y1>y2) swap(y1,y2);
                printf("%d\n",query(x1,x2,y1,y2,rect));
            }
        }
    }
}

  最后要注意的一点是,查询时的两点坐标不一定是升序的,如果x1大于x2,就要交换过来。。。这个坑了我很久。。。

posted @ 2013-05-29 22:56  SF-_-  阅读(239)  评论(0编辑  收藏  举报