描述
XXX实现了一个大整数模板(十进制) 。他的大整数有一个十分厉害的功能:它可以像提 取子串那样提取出整数中的一段。当然,这提取出的一段也是大整数。不过,XXX发现 他的模板中这种操作的效率很低,于是想请你帮他实现这样一个功能。也就是说,在给出一 个长度为 N 的大整数后,你的程序要能够快速求出大整数某一段的值。由于大整数在加减 中经常会有进位等状况发生,你的程序还需要支持区间修改操作,即将某一段中的数字全部 变成一个给定的数字。
注意:我们从大整数的最低位(最右边)开始标号,依次为第 0, 1, 2,..., N - 1 位。
输入
第一行两个整数 N,M,分别为大整数长度和操作数量。
第二行为长度为 N 的串表示初始的大整数。
接下来 M 行,每行描述一次操作。格式如下(第一个整数为操作类型) :
1 l r 表示询问[l, r]这一段的值
2 l r v 表示将[l, r]这一段中所有数字变为 v
输出
对每个询问操作输出一行一个整数表示对应的答案。由于大整数的值可以很大,输出答案对 10^9 + 7 取模后的结果即可。
样例输入
5 3
12345
1 1 3
2 1 4 3
1 1 3
样例输出
234
333
提示
数据约束
对于 40%的数据,N, M <= 5000。
对于另外 30%的数据,所有修改操作中 l = r。
对于 100%的数据,1 <= N, M <= 100000,0 <= l <= r <= N - 1, 0 <= v <= 9,大整数中每位数 字均在 0-9 的范围中。
。。。我被卡常了,明明log^2的复杂度QWQ。
其实随便优化就过了的,比如把所有1000..0%mod预处理出来。
不过博主实在太懒了,并且博主觉得这样写还可以练一练二分+快速幂,并且昨天没打完的红警诱惑着他,于是他懒得写了。
模拟一下pushup即可,对于覆盖要特殊处理,这里采用了分治的技巧
----------------------------------------
真香警告,看到那个UnAccepted太难受了,就去把它过了
#include<bits/stdc++.h>
const int N=100005;
const int mod=1e9+7;
#define re register
#define ll long long
using namespace std;
int n,m;
ll a[N];
template<class T>
inline void read(T &x)
{
x=0; int f=1;
static char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
x*=f;
}
inline void write(ll x)
{
if(x<0) { putchar('-'); x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
struct Tree
{
int l,r;
ll sum,cover;
}tree[4*N];
inline ll qpow(ll x,int y)
{
ll ans=1,base=x;
while(y)
{
if(y&1) ans=ans*base%mod;
base=base*base%mod;
y>>=1;
}
return ans;
}
inline void pushup(int now)
{
int y=tree[2*now+1].r-tree[2*now+1].l+1;
tree[now].sum=(tree[2*now].sum*qpow(10,y)%mod+tree[2*now+1].sum)%mod;
}
inline void build(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r; tree[now].cover=-1;
if(l==r)
{
tree[now].sum=a[l];
return;
}
int m=(l+r)>>1;
build(now<<1,l,m);
build(now<<1|1,m+1,r);
pushup(now);
}
inline ll Update(int l,int r,ll x)
{
if(l==r) return x;
int m=(l+r)>>1;
ll lc=Update(l,m,x),rc=Update(m+1,r,x);
return (lc*qpow(10,(r-(m+1)+1))%mod+rc)%mod;
}
inline void pushdown(int now)
{
if(tree[now].cover==-1) return;
ll cover=tree[now].cover;
tree[2*now].sum=Update(tree[2*now].l,tree[2*now].r,cover);
tree[2*now+1].sum=Update(tree[2*now+1].l,tree[2*now+1].r,cover);
tree[2*now].cover=tree[2*now+1].cover=cover;
tree[now].cover=-1;
}
inline void Cover(int now,int l,int r,ll x)
{
if(l<=tree[now].l&&tree[now].r<=r)
{
tree[now].sum=Update(tree[now].l,tree[now].r,x);
tree[now].cover=x;
return;
}
pushdown(now);
int m=(tree[now].l+tree[now].r)>>1;
if(l<=m) Cover(now<<1,l,r,x);
if(r>m) Cover(now<<1|1,l,r,x);
pushup(now);
}
struct S
{
int l,r;
ll sum;
};
inline S query(int now,int l,int r)
{
if(l<=tree[now].l&&tree[now].r<=r)
{
S a;
a.sum=tree[now].sum; a.l=tree[now].l; a.r=tree[now].r;
return a;
}
pushdown(now);
int m=(tree[now].l+tree[now].r)>>1;
if(r<=m) return query(now<<1,l,r);
if(l>m) return query(now<<1|1,l,r);
else
{
S ans1=query(now<<1,l,r),ans2=query(now<<1|1,l,r);
S ans; ans.sum=(ans1.sum*qpow(10,ans2.r-ans2.l+1)%mod+ans2.sum)%mod;
ans.l=ans1.l; ans.r=ans2.r;
return ans;
}
}
int main()
{
read(n); read(m);
for(int i=1;i<=n;i++)
{
char ch;
cin>>ch;
a[i]=ch-'0';
}
build(1,1,n);
int opt,l,r;
ll x;
for(re int i=1;i<=m;i++)
{
read(opt); read(l); read(r);
l++; r++; int ql=l,qr=r;
r=n-ql+1; l=n-qr+1;
if(opt==1) write(query(1,l,r).sum),putchar('\n');
if(opt==2)
{
read(x);
Cover(1,l,r,x);
}
}
return 0;
}
#include<bits/stdc++.h>
const int N=100005;
const int mod=1e9+7;
#define re register
#define ll long long
using namespace std;
int n,m;
ll Mo[N],a[N],num[10][N];
template<class T>
inline void read(T &x)
{
x=0; int f=1;
static char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
x*=f;
}
inline void write(ll x)
{
if(x<0) { putchar('-'); x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
struct Tree
{
int l,r;
ll sum,cover;
}tree[4*N];
//inline ll qpow(ll x,int y)
//{
// ll ans=1,base=x;
// while(y)
// {
// if(y&1) ans=ans*base%mod;
// base=base*base%mod;
// y>>=1;
// }
// return ans;
//}
inline void pushup(int now)
{
int y=tree[2*now+1].r-tree[2*now+1].l+1;
tree[now].sum=(tree[2*now].sum*Mo[y]%mod+tree[2*now+1].sum)%mod;
}
inline void build(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r; tree[now].cover=-1;
if(l==r)
{
tree[now].sum=a[l];
return;
}
int m=(l+r)>>1;
build(now<<1,l,m);
build(now<<1|1,m+1,r);
pushup(now);
}
inline ll Update(int l,int r,ll x)
{
return num[x][r-l+1];
}
inline void pushdown(int now)
{
if(tree[now].cover==-1) return;
ll cover=tree[now].cover;
tree[2*now].sum=Update(tree[2*now].l,tree[2*now].r,cover);
tree[2*now+1].sum=Update(tree[2*now+1].l,tree[2*now+1].r,cover);
tree[2*now].cover=tree[2*now+1].cover=cover;
tree[now].cover=-1;
}
inline void Cover(int now,int l,int r,ll x)
{
if(l<=tree[now].l&&tree[now].r<=r)
{
tree[now].sum=Update(tree[now].l,tree[now].r,x);
tree[now].cover=x;
return;
}
pushdown(now);
int m=(tree[now].l+tree[now].r)>>1;
if(l<=m) Cover(now<<1,l,r,x);
if(r>m) Cover(now<<1|1,l,r,x);
pushup(now);
}
struct S
{
int l,r;
ll sum;
};
inline S query(int now,int l,int r)
{
if(l<=tree[now].l&&tree[now].r<=r)
{
S a;
a.sum=tree[now].sum; a.l=tree[now].l; a.r=tree[now].r;
return a;
}
pushdown(now);
int m=(tree[now].l+tree[now].r)>>1;
if(r<=m) return query(now<<1,l,r);
if(l>m) return query(now<<1|1,l,r);
else
{
S ans1=query(now<<1,l,r),ans2=query(now<<1|1,l,r);
S ans; ans.sum=(ans1.sum*Mo[ans2.r-ans2.l+1]%mod+ans2.sum)%mod;
ans.l=ans1.l; ans.r=ans2.r;
return ans;
}
}
inline void INIT()
{
ll base=1;
for(int i=1;i<=n;i++)
{
base=base*10%mod;
Mo[i]=base;
}
for(int i=1;i<=9;i++)
for(int j=1;j<=n;j++)
num[i][j]=num[i][j-1]*10%mod+i;
}
int main()
{
read(n); read(m);
INIT();
for(int i=1;i<=n;i++)
{
char ch;
cin>>ch;
a[i]=ch-'0';
}
build(1,1,n);
int opt,l,r;
ll x;
for(re int i=1;i<=m;i++)
{
read(opt); read(l); read(r);
l++; r++; int ql=l,qr=r;
r=n-ql+1; l=n-qr+1;
if(opt==1) write(query(1,l,r).sum),putchar('\n');
if(opt==2)
{
read(x);
Cover(1,l,r,x);
}
}
return 0;
}