zoj3813 Alternating Sum 较难的线段树
来源:互联网 发布:买家淘宝怎么提升信誉 编辑:程序博客网 时间:2024/04/29 14:42
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:
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
设F(l,r)为the sum of G(i, j) 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;}
- zoj3813 Alternating Sum 较难的线段树
- zoj3813 线段树
- zoj 3813 Alternating Sum(线段树)
- zoj 3813 Alternating Sum(线段树)
- [ZOJ 3813 Alternating Sum] 线段树 树状数组
- 2014牡丹江网络预选赛E题(线段树)zoj3813
- HDU 3397(线段树,较难~)
- ZOJ 3813 Alternating Sum
- zoj 3813 Alternating Sum
- GYM 100712 L.Alternating Strings II(dp+线段树)
- poj 2828 Buy Tickets(线段树中单点更新较难的题目)
- HDU 3397 线段树 较麻烦
- ZOJ 3813 Alternating Sum 树状数组
- poj 2528 Mayor's posters(线段树区间更新+离散化)经典题目,较难。。。
- Sum up--RMQ--线段树
- XTU1238Segment Tree(线段树)解题思想必较经典
- ZOJ 3813 Alternating Sum (牡丹江网络赛E题)
- POJ 3531 Alternating Sum of Digits 英文少
- UVA 题目760 DNA Sequencing (后缀数组求两个串最长公共子串,字典序输出)
- shell脚本(严格的终端格式控制,美丽的输出字体颜色)
- 1076. Forwards on Weibo (30)限定层数的广搜 or 最短路
- Android Studio多个module导入AAR库
- SQL总结(五)存储过程
- zoj3813 Alternating Sum 较难的线段树
- 字符运算
- Linux系统管理-终止进程/工作管理
- 开篇
- 集合
- unity3d dota 寻路
- JSF 2.0 hello world example
- HDU-2602 Bone Collector
- Android Fragment实例