hdu 4267 A Simple Problem with Integers 线段树&树状数组

A Simple Problem with Integers

Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2533    Accepted Submission(s): 822


Problem Description
Let A1, A2, ... , AN be N elements. You need to deal with two kinds of operations. One type of operation is to add a given number to a few numbers in a given interval. The other is to query the value of some element.
 

Input
There are a lot of test cases.
The first line contains an integer N. (1 <= N <= 50000)
The second line contains N numbers which are the initial values of A1, A2, ... , AN. (-10,000,000 <= the initial value of Ai <= 10,000,000)
The third line contains an integer Q. (1 <= Q <= 50000)
Each of the following Q lines represents an operation.
"1 a b k c" means adding c to each of Ai which satisfies a <= i <= b and (i - a) % k == 0. (1 <= a <= b <= N, 1 <= k <= 10, -1,000 <= c <= 1,000)
"2 a" means querying the value of Aa. (1 <= a <= N)
 

Output
For each test case, output several lines to answer all query operations.
 

Sample Input
   
   
   
   
4 1 1 1 1 14 2 1 2 2 2 3 2 4 1 2 3 1 2 2 1 2 2 2 3 2 4 1 1 4 2 1 2 1 2 2 2 3 2 4
 

Sample Output
   
   
   
   
1 1 1 1 1 3 3 1 2 3 4 1
 

Source
2012 ACM/ICPC Asia Regional Changchun Online
 

Recommend
liuyiding
 

    以前解决的都是线段树整个区间更新的问题。这还是第一次解决线段树的其他应用。这题用到了线段树的分类操作。思路来源于

http://blog.csdn.net/ophunter/article/details/9455723

写的很好很详细。

只是要注意树的结点不能写成结构体了。不然内存开不下。于是只用往函数参数上打主意了。。。

虽然有点麻烦不多节约内存的效果还是立竿见影的。。

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int N=50001;
int st[55][3*N];
int low[11]= {0,0,1,3,6,10,15,21,28,36,45};

void btree(int *sbt,int l,int r,int k,int c)
{
    int mid,ls,rs;

    sbt[k]=0;
    if(l==r)
    {
        if(c)
            scanf("%d",&sbt[k]);
        return;
    }
    ls=k<<1;
    rs=k<<1|1;
    mid=(l+r)>>1;
    btree(sbt,l,mid,ls,c);
    btree(sbt,mid+1,r,rs,c);
}
void update(int *sbt,int left,int right,int l,int r,int k,int d)
{
    int mid,ls,rs;
    if(left==l&&right==r)
    {
        sbt[k]+=d;
        return;
    }
    ls=k<<1;
    rs=k<<1|1;
    mid=(left+right)>>1;
    if(sbt[k])
    {
        sbt[ls]+=sbt[k];
        sbt[rs]+=sbt[k];
        sbt[k]=0;
    }
    if(r<=mid)
        update(sbt,left,mid,l,r,ls,d);
    else if(l>mid)
        update(sbt,mid+1,right,l,r,rs,d);
    else
    {
        update(sbt,left,mid,l,mid,ls,d);
        update(sbt,mid+1,right,mid+1,r,rs,d);
    }
}
int qu(int *sbt,int left,int right,int a,int k)
{
    int mid,ls,rs;
    if(left==right)
        return sbt[k];
    ls=k<<1;
    rs=k<<1|1;
    mid=(left+right)>>1;
    if(sbt[k])
    {
        sbt[ls]+=sbt[k];
        sbt[rs]+=sbt[k];
        sbt[k]=0;
    }
    if(a>mid)
        return qu(sbt,mid+1,right,a,rs);
    else
        return qu(sbt,left,mid,a,ls);
}
int main()
{
    int n,q,a,b,c,k,i,com,pos,sum;

    while(~scanf("%d",&n))
    {
        btree(st[0],1,n,1,1);
        for(i=1; i<55; i++)
            btree(st[i],1,n,1,0);
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d",&com);
            if(com==1)
            {
                scanf("%d%d%d%d",&a,&b,&k,&c);
                pos=low[k]+a%k;
                update(st[pos],1,n,a,b,1,c);
            }
            else
            {
                scanf("%d",&a);
                sum=0;
                for(k=1; k<=10; k++)
                {
                    pos=low[k]+a%k;
                    sum+=qu(st[pos],1,n,a,1);
                }
                printf("%d\n",sum);
            }
        }
    }
    return 0;
}

     用树状数组又写了下。速度快了很多。

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int N=50001;
int con[55][50010];//55个树状数组。思路同线段树。只是更新求和比线段树快。空间也比线段树小
int an[50010];
int low[11]= {0,0,1,3,6,10,15,21,28,36,45};
int n;
int lowbit(int x)
{
    return x&(-x);
}
void update(int* c,int x,int chan)
{
    while(x>0)
    {
        c[x]+=chan;
        x-=lowbit(x);
    }
}
int qu(int* c,int x)
{
    int s=0;
    while(x<=n)
    {
        s+=c[x];
        x+=lowbit(x);
    }
    return s;
}

int main()
{
    int q,a,b,c,k,i,com,pos,sum;

    while(~scanf("%d",&n))
    {
        memset(con,0,sizeof con);
        for(i=1;i<=n;i++)
            scanf("%d",an+i);
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d",&com);
            if(com==1)
            {
                scanf("%d%d%d%d",&a,&b,&k,&c);
                pos=low[k]+a%k;
                update(con[pos],b,c);
                update(con[pos],a-1,-c);
            }
            else
            {
                scanf("%d",&a);
                sum=an[a];
                for(k=1; k<=10; k++)
                {
                    pos=low[k]+a%k;
                    sum+=qu(con[pos],a);
                }
                printf("%d\n",sum);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(c,算法,ACM)