JZOJsenior1384. Alice的游戏
来源:互联网 发布:mac系统 流程图 编辑:程序博客网 时间:2024/05/19 11:46
题目描述
Description
Alice又想到一个游戏:N个数每个数都在0到9之间,可以对每一个数进行加1操作,但这个加1比较特别,0-8加1后会相应变成1-9,但9加1后会变成0,给出N个数,进行M次操作,每次操作都会给出两个整数A和B(1<=A<=B<=N),要求输出第A个数到第B个数的和,然后把A到B之间的每一个数进行一次加1操作。
你能帮助Alice吗?
Input
输入文件第一行包含两个整数N和M(1<=N<=250000,1<=M<=100000);
第二行N个数字,每个数字都在0到9之间,中间没有空格,表示初始值。
接下来M行,每行包含两个整数A和B(1<=A<=B<=N)
Output
输出M行,每行表示对应区间的和,注意是先计算后操作。
Sample Input
输入1:
4 3
1234
1 4
1 4
1 4
输入2:
4 4
1234
1 1
1 2
1 3
1 4
输入3:
7 5
9081337
1 3
3 7
1 3
3 7
1 3
Sample Output
输出1:
10
14
18
输出2:
1
4
9
16
输出3:
17
23
1
19
5
Data Constraint
Hint
【数据范围】
30%的数据N,M<=1000
思路
这题的正解是线段树,不过比普通线段树难搞很多
这里的线段树每一个点维护一个0~9的序列,表示0~9出现了多少次
每次修改时就把0~8改到1~9的次数,9改成0的次数,然后再下传标记
由于转x次相当于转x%10次,所以这里相当于一个小优化
打起来比较麻烦,而且还有一个大坑——
pascal卡常!思路完全对!答案是对的!超了几百+ms!woc……mdzz……RNMMP……
于是怒改c++强行开O3切掉,只不过code极其难看……
pascal code(70分)
type point=record sum,flag,p:longint; a:array[0..9]of longint; end;var tree:array[0..1234567]of point; n,m,i,j,x,y:longint; ch:char;procedure update(x:longint);var i,k:longint;begin tree[x].p:=tree[x].p mod 10; for i:=1 to tree[x].p do begin k:=tree[x].a[9]; for j:=9 downto 1 do tree[x].a[j]:=tree[x].a[j-1]; tree[x].a[0]:=k; end; tree[x].sum:=0; for i:=0 to 9 do inc(tree[x].sum,tree[x].a[i]*i); tree[x].p:=0;end;procedure downdata(x:longint);var i,j,k:longint;begin inc(tree[2*x].flag,tree[x].flag); inc(tree[2*x+1].flag,tree[x].flag); inc(tree[2*x+1].p,tree[x].flag); inc(tree[2*x].p,tree[x].flag); tree[x].flag:=0; update(x*2); update(x*2+1); update(x); tree[x].flag:=0;end;procedure maketree(x,l,r:longint);var i,mid:longint;begin if l=r then begin read(ch); tree[x].a[ord(ch)-48]:=1; tree[x].sum:=ord(ch)-48; exit; end; mid:=(l+r)shr 1; maketree(2*x,l,mid); maketree(2*x+1,mid+1,r); tree[x].sum:=tree[2*x].sum+tree[2*x+1].sum; for i:=0 to 9 do tree[x].a[i]:=tree[2*x].a[i]+tree[2*x+1].a[i];end;function solve(x,y,t,l,r:longint):longint;var mid:longint;begin downdata(t); if (l>=x)and(r<=y)then begin exit(tree[t].sum); end; mid:=(l+r)shr 1; if mid>=y then exit(solve(x,y,2*t,l,mid)) else if mid<x then exit(solve(x,y,2*t+1,mid+1,r)) else exit(solve(x,y,2*t,l,mid)+solve(x,y,2*t+1,mid+1,r));end;procedure change(t,l,r,x,y:longint);var i,j,k,mid:longint;begin downdata(t); if (l>=x)and(r<=y)then begin inc(tree[t].flag); inc(tree[t].p); downdata(t); exit; end; mid:=(l+r)shr 1; if y<=mid then change(2*t,l,mid,x,y) else if x>mid then change(2*t+1,mid+1,r,x,y) else begin change(2*t,l,mid,x,y); change(2*t+1,mid+1,r,x,y); end; tree[t].sum:=tree[t*2].sum+tree[t*2+1].sum; for i:=0 to 9 do tree[t].a[i]:=tree[2*t].a[i]+tree[2*t+1].a[i];end;begin readln(n,m); maketree(1,1,n); for i:=1 to m do begin readln(x,y); writeln(solve(x,y,1,1,n)); change(1,1,n,x,y); end;end.
c++ code(AC)
#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include<bits/stdc++.h>using namespace std;int f[1020251],a[264451],s[1020251],p[1020251],val[1020251][10];int n,m,t,l,r,c,nn;char str[264451];void tsum(int v){ f[v]=f[v*2]+f[v*2+1]; for(int i=0;i<=9;i++) { val[v][i]=val[v*2][i]+val[v*2+1][i]; }}void maketree(int v,int l,int r){ if(l==r) { f[v]=a[l]; val[v][a[l]]++; return; } int mid=(l+r)>>1; maketree(v*2,l,mid); maketree(v*2+1,mid+1,r); tsum(v);}void update(int x){ if(x>=nn)return; int o[10]; for(int i=0;i<10;i++)o[(i+p[x])%10]=val[x][i]; memcpy(val[x],o,sizeof(o)); f[x]=0; for(int i=0;i<10;i++) f[x]+=val[x][i]*i; p[x]=0;}void doit(int v){ s[v*2]+=s[v],s[v*2+1]+=s[v],p[v*2]+=s[v],p[v*2+1]+=s[v],s[v]=0; update(v*2); update(v*2+1); update(v);}void change(int v,int l,int r,int x,int y){ if(l==x && r==y) { s[v]++; p[v]++; update(v); return; } doit(v); int mid=(l+r)/2; if(y<=mid)change(v*2,l,mid,x,y); if(x>mid)change(v*2+1,mid+1,r,x,y); if(!(y<=mid||x>mid)){ change(v*2,l,mid,x,mid); change(v*2+1,mid+1,r,mid+1,y); } tsum(v);}int find(int v,int l,int r,int x,int y){ if(l==x&&r==y) { return f[v]; } doit(v); int mid=(l+r)/2; if(x>mid)return find(v*2+1,mid+1,r,x,y); if(y<=mid)return find(v*2,l,mid,x,y); return find(v*2,l,mid,x,mid)+find(v*2+1,mid+1,r,mid+1,y);}int main(){ scanf("%d%d%s",&n,&m,str+1); for(int i=1;i<=n;i++)a[i]=int(str[i])-48; t=n,nn=1; for(;t>1;t=(t+1)/2,nn*=2); nn*=2; maketree(1,1,n); while(m--) { scanf("%d%d",&l,&r); printf("%d\n",find(1,1,n,l,r)); change(1,1,n,l,r); }}
- JZOJsenior1384. Alice的游戏
- Alice 与 Bob 的游戏 (概率DP)
- JZOJ1384. Alice的游戏(2017.8B组)
- 【其他】【RQNOJ】永远的Alice
- Alice和Bob的故事
- uvalive 5760 Alice and Bob (组合游戏,dp)
- 4730: Alice和Bob又在玩游戏
- Alice And Bob Hdu--复杂的贪心
- 支付宝alice的表单验证
- BZOJ4730 UOJ#266【清华集训2016】Alice和Bob又在玩游戏
- bzoj 4730: Alice和Bob又在玩游戏 线段树合并&博弈论
- [清华集训2016][UOJ266][BZOJ4730] Alice和Bob又在玩游戏 sg函数+字典树
- Sicily 1732 Alice and Bob (二进制数的最大公约数)
- HDU 4268 Alice and Bob(贪心+Multiset的应用)
- 杭电acm 4268 Alice and Bob set的运用
- 关于man gittutorial中Alice和Bob权限的说明
- 你了解nginx location 的root和alice吗
- Bob喜欢Alice很久了,他对Alice的一点一滴都非常在意,这不今天有同学提到有一篇文章里提到了Alice,这下Bob着急了, 赶紧找来了那篇文章,焦急找寻着Alice这个名字,他想知道Alice
- SSD生成LMDB报错:ssd ImportError: No module named caffe.proto
- 朴素贝叶斯
- webservice
- java StringBuilder类中的常用方法 及StringBuilder与StringBuffer的区别
- JS中操作数组的常用函数
- JZOJsenior1384. Alice的游戏
- centos7下KVM的网桥模式配置
- MFC菜单栏的创建和使用
- Java Collections的min和max方法
- String的使用
- C语言及程序设计初步 Lesson 7 项目:1计算正差值,2判断输出三个整数中的最大值,3计算周工资
- 等差数列
- SpringAOP技术学习---Day1
- URDF文件的生成和编写(四)