hdu1892 (summer III see you)

本题也属于比较简单的二维树状数组问题。

思路很简单:单点向上记录,向下求和,不过一直AC不了,总结一下每次出现错误的原因:

1、一开始mle。。。后来查了一下,是因为数组开得太大,看来数组还是要看情况来开,根据情况,适合就好。

2、然后就是各种WA。。。对比AC代码后发现,是因为一下两个原因:a、对于单点书本的判断的表达式书写出错。(应该和区域的计算表达式差不多) b、除了add外其他的update函数在更新时坐标都不需要+1,因为add的时候,已经从(1,1)开始取,所以后面的其他操作也就不用+1。

3、当我以为这些问题都解决,可以AC时,OJ抛出了了个TLE。。。检查了好多遍感觉都不会T啊,可是事实就是如此残忍。。。在我把主算法一个个换走后发现,原来是if-else太多引起的问题。原来if-else 也会增加复杂度。以后应该要对题目给出的数据敏感一点,如<=10,就是为了让我用for循环进行初始化c数组为1。,


先附上AC代码(此为转载的代码,因为自己后来修改的版本已经几乎接近这个了,所以直接上这个):

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int size = 1010;
int a[size+1][size+1];

int lowbit(int i)
{
    return i & (-i);
}

void add(int x, int y, int num)
{
    for(int i = x; i <= size; i += lowbit(i))
        for(int j = y; j <= size; j += lowbit(j))
            a[i][j] += num;
}

int getSum(int x, int y)
{
    int tot = 0;
    for(int i = x; i > 0; i -= lowbit(i))
        for(int j = y; j > 0; j -= lowbit(j))
            tot += a[i][j];
    return tot;
}

void init()
{
    memset(a, 0, sizeof(a));
    for(int i = 1; i < size; ++i)
        for(int j = 1; j < size; ++j)
            add(i, j, 1);
}



int main()
{
    int T, n, x1, x2, y1, y2, n1;
    char cmd[3];
    scanf("%d", &T);
    for(int cnt = 1; cnt <= T; ++cnt)
    {
        init();
        scanf("%d", &n);
        printf("Case %d:\n", cnt);
        while(n--)
        {
            scanf("%s", cmd);
            if(cmd[0] == 'A')
            {
                scanf("%d%d%d", &x1, &y1, &n1);
                add(x1+1, y1+1, n1);
            }
            else if(cmd[0] == 'S')
            {
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                ++x1;
                ++x2;
                ++y1;
                ++y2;
                if(x1 > x2)
                    swap(x1, x2);
                if(y1 > y2)
                    swap(y1, y2);
                int temp;
                temp=getSum(x2,y2)-getSum(x1-1,y2)-getSum(x2,y1-1)+getSum(x1-1,y1-1);
                printf("%d\n",temp);
            }
            else if(cmd[0] == 'D')
            {
                scanf("%d%d%d",&x1,&y1,&n1);
                ++x1;
                ++y1;
                int temp;
                temp=getSum(x1,y1)-getSum(x1-1,y1)-getSum(x1,y1-1)+getSum(x1-1,y1-1);
                if(n1 > temp)
                    n1 = temp;
                add(x1, y1, -n1);
            }
            else if(cmd[0] == 'M')
            {
                scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &n1);
                ++x1;
                ++x2;
                ++y1;
                ++y2;
                int temp;
                temp=getSum(x1,y1)-getSum(x1-1,y1)-getSum(x1,y1-1)+getSum(x1-1,y1-1);
                if(n1 > temp)
                    n1 = temp;
                add(x1, y1, -n1);
                add(x2, y2, n1);
            }
        }
    }
    return 0;
}

TLE:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1011;
int c[maxn+1][maxn+1],n,casenum,cases=0,queries;
char str[10];


int lowbit(int x)
{
    return x&(-x);
}

void update(int i,int j,int val)
{
   for(int x=i;x<maxn;x+=lowbit(x))
    for(int y=j;y<maxn;y+=lowbit(y))
   {
       c[x][y]+=val;
   }
}


int getsum(int i,int j)
{
   int result=0;
   for(int x=i;x>0;x-=lowbit(x))
   {
       for(int y=j;y>0;y-=lowbit(y)){
        result+=c[x][y];
       }
   }
   return result;
}

void init()
{
           memset(c,0,sizeof(c));
           for(int i=1;i<maxn;i++)
            for(int j=1;j<maxn;j++)
            update(i,j,1);
}
int main()
{
    scanf("%d",&casenum);
    while(casenum--)
    {
        cases++;
        printf("Case %d:\n",cases);
        init();
        scanf("%d%*c",&queries);
        for(int i=1;i<=queries;i++)
        {
            scanf("%s",str);
            if(str[0]=='S')
            {
                int x1,x2,y1,y2,n1,n2,m1,m2,sum;
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                n1=max(x1,x2);
                n2=min(x1,x2);
                m1=max(y1,y2);
                m2=min(y1,y2);
                sum=getsum(n1+1,m1+1)-getsum(n2,m1+1)-getsum(n1+1,m2)+getsum(n2,m2);
                printf("%d\n",sum);
            }
            if(str[0]=='A')
            {
                int xx,yy,nn;
                scanf("%d%d%d",&xx,&yy,&nn);
                update(xx+1,yy+1,nn);
            }
            if(str[0]=='D')
            {
                int xxx,yyy,nnn,t;
                scanf("%d%d%d",&xxx,&yyy,&nnn);
                t=getsum(xxx,yyy)-getsum(xxx,yyy+1)-getsum(xxx+1,yyy)+getsum(xxx,yyy);
                if(t<=nnn)
                    update(xxx,yyy,-t);
                    else
                        update(xxx,yyy,-nnn);
            }
            if(str[0]=='M')
            {
                int xx1,xx2,yy1,yy2,tt,nnnn;
                scanf("%d%d%d%d%d",&xx1,&yy1,&xx2,&yy2,&nnnn);
                tt=getsum(xx1+1,yy1+1)-getsum(xx1,yy1+1)-getsum(xx1+1,yy1)+getsum(xx1,yy1);
                if(nnnn>=tt)
                {
                    update(xx1,yy1,-tt);
                    update(xx2,yy2,tt);
                }
                else
                {
                    update(xx1,yy1,-nnnn);
                    update(xx2,yy2,nnnn);
                }
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值