2016 UESTC Training for Data Structures O - 卿学姐种美丽的花 树状数组+等差数列

来源:互联网 发布:剑三明教脸型数据 编辑:程序博客网 时间:2024/04/28 23:33

O - 卿学姐种美丽的花

Time Limit: 8000/4000MS (Java/Others)     Memory Limit: 125535/65535KB (Java/Others)
 

众所周知,在喵哈哈村,有一个温柔善良的卿学姐。

卿学姐喜欢和她一样美丽的花。所以卿学姐家的后院有很多的花坛。

卿学姐有n个花坛,一开始第ii个花坛里有A[i]  朵花。每过一段时间,卿学姐都会在花坛里种上新的花。

作为一个聪明的学姐,卿学姐的种花方式也是与众不同 , 每一次,卿学姐会在第xx个花坛种上yy朵花,然后在第x+1个花坛

上种上y1朵花,再在第x+2个花坛上种上y2朵花......以此类推,直到种到最后一个花坛,或者不需要种花为止。

喵哈哈的村民们都喜欢去卿学姐的后院赏花,沈宝宝也不例外。然而沈宝宝可不是省油的灯,怎么可能会老老实实地赏花呢。

每次沈宝宝来时,都会随机询问卿学姐在第ii个花坛有多少朵花。

花坛的花实在太多了,卿学姐实在是数不过来。于是现在她向你求助,希望你能帮她数出花坛里多少朵花。

Input

第一行输入两个整数,花坛个数NN和操作次数QQ

第二行N个整数A[1],A[2],A[3].....A[N]          。 ( 1A[i]231     )

接下来Q行,每行一个操作。

  1. 1 x y 表示卿学姐会在xx号花坛种yy朵花,并按相应的规律在后面的花坛上种花。

  2. 2 x 表示沈宝宝问卿学姐第xx个花坛有多少朵花。

数据保证:

  • 1N106                  

  • 1Q2106                         

  • 对于操作 1 , 1xN1y109

  • 对于操作 2 , 1xN

Output

对于每个询问操作,按顺序输出答案对772002+233取模的值。

Sample input and output

Sample InputSample Output
6 31 2 3 2 1 21 2 32 32 6
52

Source

2016 UESTC Training for Data Structures  Problem O

My Solution

树状数组+等差数列

更的时候 Ax = A0 + (x-x0)*(-1)

所以Ax求和并加上初始值就是新的val[x]了,这个最后加上初始值直接输出就行

sum(Ax) = sum(A0+x0) - sum(x更新的次数)

然后A0 + x0用一个树状数组维护,在更新点add(x0, A0+x0); 并在更新结尾的地方 add(x0+y0, -(x0+y0)),

这样用树状数组地方get()的时候就不会对后面没有更新到的地方有影响了

用另一个数组维护x出现的次数,在更新点add(x0, 1); 并在更新结尾的地方 add(x0+y0, -1), 同理对后面没有影响了

复杂度 O(q*logn)


#include <iostream>#include <cstdio>#include <cstring>using namespace std;typedef long long LL;const int maxn = 1e6 +8;//!A0 = sum(A0 + (x-x0)*(-1) ); ==> Ax = sum(A0+x0) - sum(x被更新的次数)LL Tree[maxn], Tree2[maxn];   //Tree 记录 sum( )  Tree 记录 x 被更新的次数int n, val[maxn];inline int lowbit(int x){    return (x&-x);}void add(int x, int value){    for(int i = x; i <= n; i+= lowbit(i))        Tree[i] += value;}LL get(int x){    LL sum = 0;    for(int i = x;i;i-=lowbit(i))        sum+=Tree[i];    return (sum);}//Tree2void add2(int x, int value){    for(int i = x; i <= n; i+= lowbit(i))        Tree2[i] += value;}LL get2(int x){    LL sum = 0;    for(int i = x;i;i-=lowbit(i))        sum+=Tree2[i];    return (sum);}int main(){    #ifdef LOCAL    freopen("a.txt", "r", stdin);    #endif // LOCAL    int q;    memset(Tree, 0, sizeof Tree);    memset(Tree2, 0, sizeof Tree2);    scanf("%d%d", &n, &q);    for(int i = 1; i <= n; i++){        scanf("%d", &val[i]);    }    int op, x, y;    while(q--){        scanf("%d", &op);        if(op == 1){            scanf("%d%d", &x, &y);            add(x, x+y);            if(x+y <= n) add(x+y, -(x+y));     //!在更新的结尾处加上个 - (x+y) 这样对后面没有更新到的地方就没有影响了 后面都抵消为 0 了            add2(x, 1);            if(x+y <= n) add2(x+y, -1);        //!在更新的结尾处加上个 - 1 这样对后面没有更新到的地方就没有影响了 后面都抵消为 0 了        }        else{            scanf("%d", &x);            //t = -get(x-1);            LL ans = get(x) - x*get2(x) + val[x];            printf("%d\n", int( ans % (772002+233)));  //get(0) == 0        }    }    return 0;

Thank you!

                                                                                                                                               ------from ProLights
0 0