线段树(树状数组)hdu4267

来源:互联网 发布:金手指炒股软件 编辑:程序博客网 时间:2024/06/05 22:43

Online JudgeOnline ExerciseOnline TeachingOnline ContestsExercise AuthorF.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts

Problem Archive
Realtime Judge Status
Authors Ranklist
 
     C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests 
    DIY | Web-DIY beta
Recent Contests
Author lee
Mail Mail 0(0)
Control Panel Control Panel 
Sign Out Sign Out

***重磅消息——[BestCoder Round #4]冠军将获得iPad Mini一部! 
《BestCoder用户手册》下载

A Simple Problem with Integers

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


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 1142 12 22 32 41 2 3 1 22 1 2 22 32 41 1 4 2 12 12 22 32 4
 

Sample Output
111113312341


又是一道神奇的题目。。。

这个题是对区间内不同的数加上一个值,但线段树只能维护连续的区间,所以这里我们按照k进行分组,根据(i-a)%k==0  -->  i%k=a%k。

分组后一共有55中情况:

1,2,3,4,5......
1,3,5,7,9......
2,4,6,8,10....
1,4,7,10,13...
2,5,9,12,15...
3,6,10,13,16...

这样输入a,b,就可以定位到tree[k][a%k]这一组,然后对组内进行成段更新,线段树和树状数组都可以。

Tips:

树状数组的优势是方便动态求值和更新..

可惜树状数组是单点更新

倒是有个方法可以快速成段更新

就是在区间[a, b]内更新+x就在a的位置+x 然后在b+1的位置-x

求某点a的值就是求数组中1~a的和..



树状数组代码:

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=50010;int n,a[maxn];struct BIT{    int val[maxn];    void clear(){memset(val,0,sizeof(val));}    int lowbit(int x)    {        return x&(-x);    }    void update(int s,int e,int x)    {        while(e>0)        {            val[e]+=x;            e-=lowbit(e);        }        s--;        while(s>0)        {            val[s]-=x;            s-=lowbit(s);        }    }    int getsum(int x)    {        int sum=0;        while(x<maxn)        {            sum+=val[x];            x+=lowbit(x);        }        return sum;    }}tree[12][12];int main(){    while(scanf("%d",&n)!=EOF)    {        for(int i=1;i<=n;i++)scanf("%d",&a[i]);        for(int i=0;i<=10;i++)            for(int j=0;j<=10;j++)tree[i][j].clear();        int q;        scanf("%d",&q);        while(q--)        {            int op,l,r,k,x;            scanf("%d",&op);            if(op==1)            {                scanf("%d%d%d%d",&l,&r,&k,&x);                tree[k][l%k].update(l/k+1,l/k+(r-l)/k+1,x);            }            else            {                scanf("%d",&x);                int sum=0;                for(int i=1;i<=10;i++)                    sum+=tree[i][x%i].getsum(x/i+1);                printf("%d\n",sum+a[x]);            }        }    }    return 0;}

线段树代码(别人的):

#include<algorithm>#include<cstdio>#include<string.h>#include<vector>using namespace std;const int N=50010;int sum[N<<2][55];int col[N<<2],res[N];#define lson l,mid, rt << 1#define rson  mid+1,r,rt << 1 | 1int mod,LL;int shunxu[11][11];void PushDown(int rt){    if(col[rt])    {        col[rt<<1] += col[rt];        col[rt<<1|1] += col[rt];        col[rt]=0;        for(int i=0; i<55; i++)        {            sum[rt<<1][i] += sum[rt][i];            sum[rt<<1|1][i] += sum[rt][i] ;            sum[rt][i]=0;        }    }}void build(int l,int r,int rt){    col[rt]=0;    memset(sum[rt],0,sizeof(sum[rt]));    if(l==r)        return;    int mid=(l+r)>>1;    build(lson);    build(rson);}void update(int L,int R,int val,int l,int r,int rt){    if(l==L&&r==R)    {        col[rt]+=val;        sum[rt][shunxu[mod][LL%mod]]+=val;        return ;    }    PushDown(rt);    int mid=(l+r)>>1;    if(R<=mid)update(L,R,val,lson);    else if(L>mid)update(L,R,val,rson);    else    {        update(L,mid,val,lson);        update(mid+1,R,val,rson);    }}int query(int l,int r,int rt,int m){    if(l==r)    {        int d=0;        for(int i=1; i<=10; i++)            d += sum[rt][shunxu[i][m%i]];        return d+res[l];    }    int mid=(l+r)>>1;    PushDown(rt);    if(m<=mid)        return query(lson,m);    else return query(rson,m);}int main(){    int n,q,cc=0;    for(int i=1; i<=10; i++)        for(int j=0; j<i; j++)            shunxu[i][j]=cc++;    while(~scanf("%d",&n))    {        build(1,n,1);        int q;        for(int i=1; i<=n; i++)            scanf("%d",&res[i]);        scanf("%d",&q);        int kk,aa,RR,k,val;        while(q--)        {            scanf("%d",&kk);            if(kk==2)            {                scanf("%d",&aa);                printf("%d\n",query(1,n,1,aa));            }            else if(kk==1)            {                scanf("%d%d%d%d",&LL,&RR,&mod,&val);                update(LL,RR,val,1,n,1);            }        }    }    return 0;}




0 0
原创粉丝点击