zoj 3813 Alternating Sum(2014ACMICPC Regional 牡丹江站網路賽 E),zoj2014acmicpc

來源:互聯網
上載者:User

zoj 3813 Alternating Sum(2014ACMICPC Regional 牡丹江站網路賽 E),zoj2014acmicpc

Alternating SumTime 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(l, r) = 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:

  • 1 x d: set Px to d, d is a single digit.
  • 2 l r: find the sum of G(i, j) 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:

  • 1 x d (1 <= x <= length(P), 0 <= d <= 9)
  • 2 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
Author: LIN, Xi

Source: The 2014 ACM-ICPC Asia Mudanjiang Regional First Round


http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3813


思路:題目意思很清楚了,這裡只說思路。

設區間[L,R],區間長度為len=(R-L+1),設F[i]表示G(i,i)+G(i,i+1)+......G(i,R)。那麼對於區間[L,R],詢問的答案即為Ans[L,R]=F[L]+F[L+1]+......+F[R]。容易得到G[i,j]=Si-G(i+1,j),所以F[i]=(R-i+1)*Si-F[i+1]。即F[i]+F[i+1]=(R-i+1)*Si。

那麼Ans[L,R]=len*SL+(len-2)*S(i+2)+.....SR(len為奇數)或

      len*SL+(len-2)*(L+2)+......+2*S(R-1)(len為偶數)。

那麼對於給定區間[L,R]的答案可以用線段樹維護,我的線段樹維護4個值,sum[0]表示區間中偶數位元的和,sum[1]表示區間中奇數位置的和,tsum[0]表示Ans[L+1,R],tsum[1]表示Ans[L,R]。

如區間[3,7]={2,3,4,5,6},那麼sum[0]=3+5=8,sum[1]=2+4+6=12,tsum[0]=4*3+2*5=22,tsum[1]=5*2+3*4+1*6=28。對於區間長度為偶數的類似。

現在考慮合并兩個區間,對於區間p,其左兒子為lson,右兒子為rson。sum[0],sum[1]很好合并,只需要考慮左兒子長度的奇偶性,既可以完成合併。對於tsum[0],其左部分(由左兒子的資訊得到的部分)為左兒子的tsum[0]加上左兒子的sum[0]乘以右兒子的長度(自己推推就能知道)。右部分要根據左兒子長度的奇偶性來決定是右兒子的tsum[0]還是tsum[1]。對於tsum[1]也類似。


那麼線段樹部分就結束了。注意到題目中的數字區間是一個模式串重複無數次的一個無限長的串,那麼所給的區間可能會橫跨很多個模式串S,我們的線段樹只是對於模式串S的線段樹,那麼對於超出一個模式串的部分不能只用線段樹來解決。如果區間[L,R]橫跨多個模式串,那麼將區間L,R分成三部分,首碼pre,中間部分mid,尾碼suf,首碼表示區間[L,R]第一個不完整的模式串(可為空白),尾碼表示最後一個不完整的模式串(可為空白),中間部分為中間橫跨的多個完整的模式串(可為空白)。那麼pre,suf可以用線段樹求出,類似於區間合并的方法,這裡不再贅述。設mid包括n個完整的模式串,suf的長度為Len。還是按照區間合并的思想,不過這裡n可能很大,不能直接一個一個地合并,事實上可以推出來,具體公式請自己推吧,本人很懶。。。。

這裡還有一個問題,如果模式串為奇數,那麼合并的時候很煩人,要間隔地考慮,這裡我將模式串擴大兩倍,保證模式串為偶數,那麼在求mid的值得時候就不需要考慮奇偶性了。但是如果將模式串擴大兩倍的話,在修改操作的時候,一定要記住要修改兩個位置(這裡忘了WA了10+發。。。。。。)。恩,大概就是這樣,下面是代碼:(記憶體耗得飛起。。。。速度也比較慢~~)

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#define maxn 200010#define mid ((t[p].l+t[p].r)>>1)#define ls (p<<1)#define rs (ls|1)#define ll long long#define mod 1000000007using namespace std;char st[maxn];struct tree{    ll l,r;    ll sum[2],tsum[2];}t[maxn<<2];void pushup(int p){    ll l=t[ls].r-t[ls].l+1;    ll r=t[rs].r-t[rs].l+1;    if(l%2)    {        t[p].sum[0]=(t[ls].sum[0]+t[rs].sum[1])%mod;        t[p].sum[1]=(t[ls].sum[1]+t[rs].sum[0])%mod;        t[p].tsum[0]=(t[ls].tsum[0]+r*t[ls].sum[0]%mod+t[rs].tsum[1])%mod;        t[p].tsum[1]=(t[ls].tsum[1]+r*t[ls].sum[1]%mod+t[rs].tsum[0])%mod;    }    else    {        t[p].sum[0]=(t[ls].sum[0]+t[rs].sum[0])%mod;        t[p].sum[1]=(t[ls].sum[1]+t[rs].sum[1])%mod;        t[p].tsum[0]=(t[ls].tsum[0]+r*t[ls].sum[0]%mod+t[rs].tsum[0])%mod;        t[p].tsum[1]=(t[ls].tsum[1]+r*t[ls].sum[1]%mod+t[rs].tsum[1])%mod;    }}void build(int p,int l,int r){    t[p].l=l,t[p].r=r;    t[p].sum[0]=t[p].sum[1]=t[p].tsum[0]=t[p].tsum[1]=0;    if(l==r)    {        t[p].sum[0]=t[p].tsum[0]=0;        t[p].sum[1]=t[p].tsum[1]=st[l]-'0';        return;    }    build(ls,l,mid);    build(rs,mid+1,r);    pushup(p);}void modify(int p,int po,ll d){    if(t[p].l==t[p].r)    {        t[p].sum[1]=t[p].tsum[1]=d;        return;    }    if(po>mid)    modify(rs,po,d);    else    modify(ls,po,d);    pushup(p);}tree query(int p,ll l,ll r){    tree tmp;    if(t[p].l==l&&t[p].r==r)    {        return t[p];    }    if(l>mid)    return query(rs,l,r);    else if(r<=mid)    return query(ls,l,r);    else    {        tree t1=query(ls,l,mid);        tree t2=query(rs,mid+1,r);        tmp.l=t1.l,tmp.r=t2.r;        ll l=t1.r-t1.l+1;        ll r=t2.r-t2.l+1;        if(l%2){            tmp.sum[0]=(t1.sum[0]+t2.sum[1])%mod;            tmp.sum[1]=(t1.sum[1]+t2.sum[0])%mod;            tmp.tsum[0]=(t1.tsum[0]+r*t1.sum[0]%mod+t2.tsum[1])%mod;            tmp.tsum[1]=(t1.tsum[1]+r*t1.sum[1]%mod+t2.tsum[0])%mod;        }        else{            tmp.sum[0]=(t1.sum[0]+t2.sum[0])%mod;            tmp.sum[1]=(t1.sum[1]+t2.sum[1])%mod;            tmp.tsum[0]=(t1.tsum[0]+r*t1.sum[0]%mod+t2.tsum[0])%mod;            tmp.tsum[1]=(t1.tsum[1]+r*t1.sum[1]%mod+t2.tsum[1])%mod;        }        return tmp;    }}ll getsum(ll num,ll len,ll left,int typ){    if(num==0)    return 0;    ll sum=0;    sum=num%mod*t[1].tsum[typ]%mod;    ll tt;    if(num%2)    tt=((num-1)/2)%mod*(num%mod);    else    tt=((num-1)%mod)*((num/2)%mod);    tt%=mod;    ll tmp=(num%mod*left%mod+tt*len%mod)%mod;    sum=(sum+tmp*t[1].sum[typ]%mod)%mod;    return sum;}int main(){  // freopen("dd.txt","r",stdin);    int ncase;    scanf("%d",&ncase);    while(ncase--)    {        scanf("%s",st);        int len=strlen(st);        for(int i=0;i<len;i++)        {            st[i+len]=st[i];        }        len*=2;        build(1,0,len-1);        int q;        scanf("%d",&q);        while(q--){            int typ;            ll ans=0,l,r;            scanf("%d",&typ);            if(typ==1)            {                int x,d;                scanf("%d%d",&x,&d);                modify(1,x-1,d);                modify(1,x-1+(len/2),d);            }            else            {                scanf("%lld%lld",&l,&r);                l--,r--;                ll lpo=l/len,rpo=r/len;                ll L=l%len,R=r%len;                if(lpo==rpo)                {                    ans=query(1,L,R).tsum[1];                }                else                {                    ll Len=((r-l+1)-(len-L))%mod;                    tree t1=query(1,L,len-1);                    tree t2=query(1,0,R);                    ans=(ans+t1.tsum[1]+Len*t1.sum[1]%mod)%mod;                    if((len-L)%2)                    ans=(ans+t2.tsum[0])%mod;                    else                    ans=(ans+t2.tsum[1])%mod;                    if((len-L)%2)                    ans=(ans+getsum(rpo-lpo-1,len,R+1,0))%mod;                    else                    ans=(ans+getsum(rpo-lpo-1,len,R+1,1))%mod;                }                printf("%lld\n",ans);            }        }    }    return 0;}





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.