hdu 树状数组小集(中低难度)

源自------------------------------------------------Ice_Crazy


树状数组水题果题模板题:hdu3792、hdu1541、hdu4046、hdu2689





hdu2838
    树状数组求逆序数果题。




hdu2433
    树状数组求顺序数,不错的题。
    sum[i~j]=val[i]+val[i+1]+...+val[j]-(j-i+1)*a;-------------(1)
    sum[i~j]=sum[j]-sum[i-1];----------------------------------(2)
    所以(1)>0等效于(2)>0。
    所以对读入的序列转化后求顺序数的对数既可。
    蛋疼的是hdu又一道必须用__int64的题,long long送掉一血。。




hdu4312
    关键是坐标系的转换:
“对于原坐标系中两点间的 Chebyshev 距离,是将坐标轴顺时针旋转45度并将
所有点的坐标值放大sqrt(2)倍所得到的新坐标系中的Manhattan距离的二分之
一。”。。既:(x,y)→(x-y,x+y),求出来的结果/2。




hdu1559
    树状数组水题。
    10秒的时间,二维树状数组(或线段树)应该也能过,不过感觉用1维的配合
着递推关系会快那么一点儿。
    下面是1维的树状数组(横向、纵向分别建立了一个,C[0]是横向的、C[1]
是纵向的)的代码。

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#define N 1011
int n,m,C[2][N][N];
int lowbit[N];
int X,Y;
int map[N][N];
void get_lowbit()
{
    int i;
    for(i=1;i<=1000;i++)    lowbit[i]=i&(-i);
}
int sum(int K,int x,int k)
{
    int p=0;
    while(0<k)
    {
        p+=C[K][x][k];
        k-=lowbit[k];
    }
    return p;
}
void update(int K,int x,int k,int dir,int limit)
{
    while(0<k && k<=limit)
    {
        C[K][x][k]+=dir;
        k+=lowbit[k];
    }
}
void get_C()
{
    int i,l;
    memset(C,0,sizeof(C));
    for(i=1;i<=n;i++)
    for(l=1;l<=m;l++)
        update(0,i,l,map[i][l],m);
    for(i=1;i<=m;i++)
    for(l=1;l<=n;l++)
        update(1,i,l,map[l][i],n);
}
int get_ans()
{
    int ans;
    int i,l;
    int temp,pre;
    ans=pre=0;
    for(i=1;i<=X-1;i++)    pre+=sum(0,i,Y-1);
    for(i=X;i<=n;i++)
    {
        temp=pre-sum(0,i-X,Y-1)+sum(0,i,Y-1);
        pre=temp;
        for(l=Y;l<=m;l++)
        {
            temp=temp-(sum(1,l-Y,i)-sum(1,l-Y,i-X))+(sum(1,l,i)-sum(1,l,i-X));
            if(temp>ans)    ans=temp;
        }
    }
    return ans;
}
int main()
{
    int T;
    int i,l;
    get_lowbit();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&n,&m,&X,&Y);
        for(i=1;i<=n;i++)
        for(l=1;l<=m;l++)
            scanf("%d",&map[i][l]);
        get_C();
        printf("%d\n",get_ans());
    }
    return 0;
}




hdu2852
    树状数组+二分。
    由于是容器,所以值为x的元素可以同时存在n多个(这个可以理解)。而删除,每次删除只删除
其中一个。。。表示无法理解,题意不清,弄得我最后无奈的看了别人的代码才检查出来,囧~~
    另外,就按照题目的“Elment”拼吧,如果感兴趣了你可以试下拼“Element”能不能ac。。。




hdu1892
    二维树状数组模板题。

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
int C[1011][1011];
int map[1011][1011];
int lowbit[1011];
int sum(int x,int y)
{
    int p=0;
    int temp=y;
    while(x>0)
    {
        y=temp;
        while(y>0)
        {
            p+=C[x][y];
            y-=lowbit[y];
        }
        x-=lowbit[x];
    }
    return p;
}
void update(int x,int y,int dir)
{
    int temp=y;
    while(x>0 && x<=1001)
    {
        y=temp;
        while(y>0 && y<=1001)
        {
            C[x][y]+=dir;
            y+=lowbit[y];
        }
        x+=lowbit[x];
    }
}
int main()
{
    int T,Case;
    int q;
    int i,l;
    char str[11];
    int x1,y1,x2,y2,z;
    int temp;
    int x_top,y_top,x_bot,y_bot;
    int a,b,c,d;
    scanf("%d",&T);
    for(Case=1;Case<=T;Case++)
    {
        scanf("%d",&q);
        memset(C,0,sizeof(C));
        for(i=1;i<=1001;i++)    lowbit[i]=i&(-i);
        for(i=1;i<=1001;i++)
        for(l=1;l<=1001;l++)
        {
            map[i][l]=1;
            update(i,l,1);
        }
        printf("Case %d:\n",Case);
        while(q--)
        {
            scanf("%s",str);
            if(str[0]=='A')
            {
                scanf("%d%d%d",&x1,&y1,&z);
                x1++;y1++;
                update(x1,y1,z);
                map[x1][y1]+=z;
            }
            else if(str[0]=='D')
            {
                scanf("%d%d%d",&x1,&y1,&z);
                x1++;y1++;
                temp=map[x1][y1]>z?z:map[x1][y1];
                update(x1,y1,-temp);
                map[x1][y1]-=temp;
            }
            else if(str[0]=='M')
            {
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&z);
                x1++;y1++;x2++;y2++;
                temp=map[x1][y1]>z?z:map[x1][y1];
                map[x1][y1]-=temp;
                map[x2][y2]+=temp;
                update(x1,y1,-temp);
                update(x2,y2,temp);
            }
            else if(str[0]=='S')
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                x1++;y1++;x2++;y2++;
                x_top=x1>x2?x1:x2;
                y_top=y1>y2?y1:y2;
                x_bot=x1>x2?x2:x1;
                y_bot=y1>y2?y2:y1;
                a=sum(x_top,y_top);
                b=sum(x_bot-1,y_bot-1);
                c=sum(x_bot-1,y_top);
                d=sum(x_top,y_bot-1);
                printf("%d\n",a-c-d+b);
            }
        }
    }
    return 0;
}




hdu2642
    二维树状数组水题。




hdu4311
    树状数组+二分(可以不用二分),当时废话的太多,我就不搬过来了, 传送~。。。




hdu2836
    (树状数组(或线段树)&&二分)&&DP,废话也比较多, 传送。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值