hdu 4267

A Simple Problem with Integers

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


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
 

题意:输入N 下面有N个数, Q个操作,对于每次操作 有两种情况。

情况1.输入1 a b k c,表示更新操作,将a-b区间内的符合a <= i <= b and (i - a) % k == 0.的数都+c。

情况2:输入2 a 表示查询操作,输出a 上的值。


如果用线段树暴力的话,妥妥的超时,需要延迟


思路:对于这种不是对整个区间都进行更新的操作,似乎lazy算法就没什么用了,这题一开始看的感觉是单点更新,但是看下数据量单点更新根本不可行。那我们可以想一下给的条件,(i-a)%k==0,可以化成i%k==a%k。对于a%k 就很好求了,所以我们可以枚举一下所有的mod 情况,因为k最大只是10,所以mod 的所有情况有55种。我们把这些mod 的情况都存下来,在更新的时候只更新(a%k)的,把(a%k)的都加起来,查询的时候在只把(i%k)的值加上,相当于用一个数组modleft[i][j]存一下某个数对于mod i 余数为j,这样就可以利用lazy的思想,只在查询的时候把值全部加起来,起到延迟标记的


#include
#include
#include
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N = 50005;
struct node
{
    int sum, lazy;
    int add[56];
}tree[N<<2];
int mod[10][10];
void build(int l,int r,int rt);
void update(int L, int R, int k, int h,int c, int l, int r, int rt);
void pushdown(int rt);
int query(int pos,int l,int r,int rt);


int main()
{
    memset(mod,0,sizeof(mod));
    int cnt=0;
    for(int i=1;i<=10;i++)
    {
        for(int j=0;j         {
            mod[i][j]=cnt++;
        }
    }
    int n;
    while(scanf("%d", &n)!=EOF)
    {
        build(1,n,1);
        int q, num, pos, a, b, k, c;
        scanf("%d", &q);
        while(q--)
        {
            scanf("%d", &num);
            if(num==1)
            {
                scanf("%d %d %d %d", &a, &b, &k, &c);
                update(a,b,k,a%k,c,1,n,1);
            }
            else
            {
                scanf("%d", &pos);
                printf("%d\n",query(pos,1,n,1));
            }
        }
    }
    return 0;
}


void build(int l,int r,int rt)
{
    memset(tree[rt].add,0,sizeof(tree[rt].add));
    tree[rt].lazy=0;
    if(l==r)
    {
        scanf("%d", &tree[rt].sum);
        return ;
    }
    int mid=(l+r)/2;
    build(lson);
    build(rson);
    return ;
}


void update(int L, int R, int k, int h, int c,int l, int r, int rt)
{
    if(l>=L&&r<=R)
    {
        tree[rt].lazy=1;
        tree[rt].add[mod[k][h]]+=c;
        return ;
    }
    pushdown(rt);
    int mid=(r+l)/2;
    if(mid>=L)
    {
        update(L,R,k,h,c,lson);
    }
    if(mid     {
        update(L,R,k,h,c,rson);
    }
    return ;
}


void pushdown(int rt)
{
    if(tree[rt].lazy)
    {
        tree[rt<<1].lazy=tree[rt<<1|1].lazy=1;
        tree[rt].lazy=0;
        for(int i=0;i<56;i++)
        {
            tree[rt<<1].add[i]+=tree[rt].add[i];
            tree[rt<<1|1].add[i]+=tree[rt].add[i];
            tree[rt].add[i]=0;
        }
    }
    return ;
}


int query(int pos,int l,int r,int rt)
{
    if(l==r)
    {
        int ans=tree[rt].sum;
        for(int i=1;i<=10;i++)
        {
            ans+=tree[rt].add[mod[i][pos%i]];
            tree[rt].add[mod[i][pos%i]]=0;
        }
        tree[rt].sum=ans;
        return ans;
    }
    int mid=(l+r)/2;
    pushdown(rt);
    if(pos<=mid)
    {
        return query(pos,lson);
    }
    else
    {
        return query(pos,rson);
    }
}

你可能感兴趣的:(线段树)