zoj3813 Alternating Sum 较难的线段树

来源:互联网 发布:买家淘宝怎么提升信誉 编辑:程序博客网 时间:2024/04/29 14:42
Alternating Sum

Time Limit: 2 Seconds      Memory Limit: 65536 KB

There is a digit string S with infinite length. In addition, S is periodic and it can be formed by concatenating infinite repetitions of a base string P. For example, if P = 3423537, then S = 3423537342353734235373423537...

Let's define the alternating sum on substrings of S. Assume Sl..r is a substring of S from index l to index r (all indexes are 1-based), then the alternating sum of Sl..r is:

G(lr) = Sl - Sl+1 + Sl+2 - ... + (-1)r-lSr

For example, S2..10 = 423537342, then G(2, 10) = 4 - 2 + 3 - 5 + 3 - 7 + 3 - 4 + 2 = -3.

Now, you are given the base string P and you have to do many operations. There are only two kinds of operations:

  • x d: set Px to dd is a single digit.
  • l r: find the sum of G(ij) that l <= i <= j <= r.

For each second operation, you should output the sum modulo 109 + 7.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains a digit string P (1 <= length(P) <= 100000).

The second line contains an integer Q (1 <= Q <= 100000) indicating the number of operations. Each of the following Q lines is an operation in such format:

  • x d (1 <= x <= length(P), 0 <= d <= 9)
  • l r (1 <= l <= r <= 1018)

Output

For each "2 l r" operation, output an integer, indicating the sum modulo 109 + 7.

Sample Input

232424242 1 12 1 41 3 72 3 432424262 1 11 3 72 2 41 3 42 7 102 1 30

Sample Output

320143820870
设F(l,r)为the sum of G(ij) that l <= i <= j <= r,长度为n,可以观察到结果为s[l]*n+s[l+2]*(n-2)+s[l+4]*(n-4)....
为了区间查询这个东西线段树的节点保存4个东西,sum[0],sum[1],tsum[0],tsum[1],分别是偶数位的和,奇数位的和,偶数位的G,奇数位的G; pushUp的操作与左半区间的长度有关。由于给出的l,r很大,得出中间完整的块数后,用类似快速幂的方法求出中间部分。
#include<iostream>#include<cstring>#include<cstdio>#include<ostream>#include<istream>#include<algorithm>#include<queue>#include<string>#include<cmath>#include<set>#include<map>#include<stack>#include<vector>#define fi first#define se second#define ll long long#define pii pair<int,int>#define inf (1<<30)#define eps 1e-8#define pb push_backusing namespace std;const int maxn=110005;const ll mod=1000000007;char p[maxn];int n;struct Node{    ll len;    ll sum[2];    ll tsum[2];    Node() { sum[0]=sum[1]=tsum[0]=tsum[1]=len=0; }}tree[maxn<<2];void pushUp(int rt){    ll u=tree[rt<<1].len;    if(u&1) {        tree[rt].sum[0]=(tree[rt<<1].sum[0]+tree[rt<<1|1].sum[1])%mod;        tree[rt].sum[1]=(tree[rt<<1].sum[1]+tree[rt<<1|1].sum[0])%mod;        tree[rt].tsum[1]=((tree[rt<<1].tsum[1]+tree[rt<<1].sum[1]*(tree[rt<<1|1].len%mod)%mod)%mod+tree[rt<<1|1].tsum[0])%mod;        tree[rt].tsum[0]=((tree[rt<<1].tsum[0]+tree[rt<<1].sum[0]*(tree[rt<<1|1].len%mod)%mod)%mod+tree[rt<<1|1].tsum[1])%mod;    }    else {        tree[rt].sum[0]=(tree[rt<<1].sum[0]+tree[rt<<1|1].sum[0])%mod;        tree[rt].sum[1]=(tree[rt<<1].sum[1]+tree[rt<<1|1].sum[1])%mod;        tree[rt].tsum[1]=((tree[rt<<1].tsum[1]+tree[rt<<1].sum[1]*(tree[rt<<1|1].len%mod)%mod)%mod+tree[rt<<1|1].tsum[1])%mod;        tree[rt].tsum[0]=((tree[rt<<1].tsum[0]+tree[rt<<1].sum[0]*(tree[rt<<1|1].len%mod)%mod)%mod+tree[rt<<1|1].tsum[0])%mod;    }    tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;}void build(int l,int r,int rt){    if(l==r) {        tree[rt].len=1;        tree[rt].sum[0]=tree[rt].tsum[0]=0;        tree[rt].sum[1]=tree[rt].tsum[1]=p[l]-'0';        return;    }    int m=(l+r)/2;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);    pushUp(rt);}void update(int x,int d,int l,int r,int rt){    if(x==l && x==r) {        tree[rt].sum[1]=tree[rt].tsum[1]=d;        return;    }    int m=(l+r)/2;    if(x<=m)        update(x,d,l,m,rt<<1);    else        update(x,d,m+1,r,rt<<1|1);    pushUp(rt);}Node mul(Node a,Node b){    Node u;    ll l=a.len;    if(l&1) {        u.sum[0]=(a.sum[0]+b.sum[1])%mod;        u.sum[1]=(a.sum[1]+b.sum[0])%mod;        u.tsum[1]=((a.tsum[1]+a.sum[1]*(b.len%mod)%mod)%mod+b.tsum[0])%mod;        u.tsum[0]=((a.tsum[0]+a.sum[0]*(b.len%mod)%mod)%mod+b.tsum[1])%mod;    }    else {        u.sum[0]=(a.sum[0]+b.sum[0])%mod;        u.sum[1]=(a.sum[1]+b.sum[1])%mod;        u.tsum[1]=((a.tsum[1]+a.sum[1]*(b.len%mod)%mod)%mod+b.tsum[1])%mod;        u.tsum[0]=((a.tsum[0]+a.sum[0]*(b.len%mod)%mod)%mod+b.tsum[0])%mod;    }    u.len=a.len+b.len;    return u;}Node query(int L,int R,int l,int r,int rt){    if(L<=l && R>=r)        return tree[rt];    int m=(l+r)/2;    Node u,v;    if(L<=m)        u=query(L,R,l,m,rt<<1);    if(R>m)        v=query(L,R,m+1,r,rt<<1|1);    return mul(u,v);}Node powMul(Node u,ll a){    if(a==0) return Node();    Node ans=powMul(u,a/2);    ans=mul(ans,ans);    if(a&1)        ans=mul(ans,u);    return ans;}int main(){    int t,q;    int x,d,ty;    ll l,r;    scanf("%d",&t);    while(t--) {        scanf("%s",p+1);        n=strlen(p+1);        build(1,n,1);        scanf("%d",&q);        while(q--) {            scanf("%d",&ty);            if(ty==1) {                scanf("%d%d",&x,&d);                update(x,d,1,n,1);            }            else {                scanf("%lld%lld",&l,&r);                ll lef=(l-1)/n+1;                ll rig=(r-1)/n+1;                int lt=l%n;                if(lt==0) lt=n;                int rt=r%n;                if(rt==0) rt=n;                if(lef==rig) {                    Node u=query(lt,rt,1,n,1);                    printf("%lld\n",u.tsum[1]);                }                else {                    Node u=query(lt,n,1,n,1);                    Node v=query(1,rt,1,n,1);                    Node o=powMul(tree[1],rig-lef-1);                    Node ans=mul(mul(u,o),v);                    printf("%lld\n",ans.tsum[1]);                }            }        }    }    return 0;}



0 0
原创粉丝点击