#1116 : 计算

来源:互联网 发布:匿名内部类java构造器 编辑:程序博客网 时间:2024/03/29 07:39

链接:
http://hihocoder.com/problemset/problem/1116?sid=615756

时间限制:4000ms
单点时限:1000ms
内存限制:256MB
描述
现在有一个有n个元素的数组a1, a2, …, an。

记f(i, j) = ai * ai+1 * … * aj。

初始时,a1 = a2 = … = an = 0,每次我会修改一个ai的值,你需要实时反馈给我 ∑1 <= i <= j <= n f(i, j)的值 mod 10007。

输入
第一行包含两个数n(1<=n<=100000)和q(1<=q<=500000)。

接下来q行,每行包含两个数i, x,代表我把ai的值改为了x。

输出
分别输出对应的答案,一个答案占一行。

样例输入
5 5
1 1
2 1
3 1
4 1
5 1
样例输出
1
3
6
10
15

这道题很明显的线段树,其中∑1 <= i <= j <= n f(i, j) 可能很多人没有明白,是指连续的在【1,n】的子集之和,我们利用前缀和和后缀和的性质,线段树维护即可。

这里的结构体里面用的是long long 为此还错了几次,我记得BC里面也有一道这样的题,特别坑爹,不过也怪我自己没有考虑周全把,哈哈。

#include<iostream>using namespace std;#include<cstdio>struct note{    long long  l,r,d,sum,q,h,j;} a[404000];const int mod_=10007;int n;void init(int i,int l,int r){    a[i].l=l;    a[i].r=r;    a[i].d=0;    a[i].sum=0;    if(l==r)        return ;    int mid=(a[i].l+a[i].r)>>1;    init(2*i,l,mid);    init(2*i+1,mid+1,r);}void insertnum(int i,int pos,int d){    if(pos==a[i].l&&pos==a[i].r)    {        a[i].d=d%mod_;        a[i].q=d%mod_;        a[i].h=d%mod_;        a[i].j=d%mod_;        a[i].sum=d%mod_;        return ;    }    int mid=(a[i].l+a[i].r)>>1;    if(pos<=mid)        insertnum(2*i,pos,d);    else        insertnum(2*i+1,pos,d);    a[i].j=(a[i<<1].j%mod_*(a[(i<<1)|1].j%mod_))%mod_;    a[i].q=(a[i<<1].q%mod_+(a[i<<1].j%mod_*a[(i<<1)+1].q%mod_))%mod_;    a[i].h=(a[i<<1 |1].j%mod_*(a[i<<1].h)%mod_+a[(i<<1)+1].h%mod_)%mod_;    a[i].sum=(a[i*2+1].sum%mod_+a[i*2].sum%mod_+a[i<<1].h%mod_*a[(i<<1)+1].q%mod_)%mod_;}int main(){    int t;    while(cin>>n>>t)    {        init(1,1,n);        while(t--)        {            int start,aim;            scanf("%d%d",&start,&aim);            insertnum(1,start,aim);            printf("%d\n",a[1].sum);        }    }    return 0;}
0 0
原创粉丝点击