分块练习
分块练习
P4109 定价
思路:
由于区间范围太大,考虑将区间分块
每 \(1e5\) 个数字分成一块,\(1\sim 10^5\) 结果为 \(5\) ,\(a\cdot10^5+1\sim(a+1)\cdot 10^5\) 结果为 \((a+1)\cdot 10^5\)
这样可以分成 \(10^4\) 个块,每次查询就是 \(O(10^5)\) 的
总时间复杂度为 \(O(T\cdot 10^5)\)
可以通过本题
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+1;
const int M=1e5;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int l[N],r[N],v[N],val[N];
inline int work(int x){
int tot=0;
for(;x;++tot,x/=10);
return tot;
}
inline int cal(int x){
while(x%10==0&&x) x/=10;
return x%10==5?work(x)*2-1:work(x)*2;
}
inline void pre(){
for(int i=1;i<N;++i){
l[i]=(i-1)*M;
r[i]=i*M;
v[i]=r[i];
val[i]=cal(i);
}
v[1]=5;
val[1]=1;
}
inline int solve(int x,int y){
int res=1e9+1,ans;
int lx=x/M+1,ly=y/M+1;
if(lx==ly){
for(int i=x;i<=y;++i){
if(res>cal(i)){
res=cal(i);
ans=i;
}
}
return ans;
}
for(int i=x;i<=r[lx];++i)
if(res>cal(i)){
res=cal(i);
ans=i;
}
for(int i=lx+1;i<=ly-1;++i)
if(res>val[i]){
res=val[i];
ans=v[i];
}
for(int i=l[ly];i<=y;++i)
if(res>cal(i)){
res=cal(i);
ans=i;
}
return ans;
}
signed main(){
pre();
int T=read();
while(T--){
int x=read(),y=read();
cout<<solve(x,y)<<endl;
}
}
CF920F SUM and REPLACE
思路:
易得 \(d(1)=1\),\(d(2)=2\),因此当一个区间内所有的数都 \(\le2\) 的时候修改操作就没有了意义
因为对于 \(\forall x\),\(d(x)\le2\cdot \sqrt x\)
所以暴力修改序列的话复杂度是 \(ok\) 的
\(so\) 这个题变成了暴力+区间求和
可以用分块
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+5;
const int M=1e6+5;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int n,m,sz;
int a[N],d[M],bl[N];
int v[N],mx[N];
int L[N],R[N];
inline void get_d(){
for(int i=1;i<(int)1e6+5;++i)
for(int j=1;i*j<(int)1e6+5;++j)
++d[i*j];
}
inline void C(int x){
v[x]=mx[x]=0;
for(int i=L[x];i<=R[x];++i){
v[x]+=a[i];
mx[x]=max(mx[x],a[i]);
}
}
inline void D(int l,int r){
for(int i=l;i<=r;++i)
if(a[i]>2) a[i]=d[a[i]];
}
inline void build(){
for(int i=1;i<=bl[n];++i)
C(i);
}
inline void update(int x,int y){
int l=bl[x],r=bl[y];
if(l==r){
D(x,y);
C(l);
return;
}
D(x,R[l]);
C(l);
D(L[r],y);
C(r);
for(int i=l+1;i<=r-1;++i)
if(mx[i]>2){
D(L[i],R[i]);
C(i);
}
}
inline int query(int x,int y){
int l=bl[x],r=bl[y];
int res=0;
if(l==r){
for(int i=x;i<=y;++i) res+=a[i];
return res;
}
for(int i=x;i<=R[l];++i) res+=a[i];
for(int i=L[r];i<=y;++i) res+=a[i];
for(int i=l+1;i<=r-1;++i) res+=v[i];
return res;
}
signed main(){
get_d();
n=read(),m=read();
sz=sqrt(n);
for(int i=1;i<=n;++i){
a[i]=read();
bl[i]=(i-1)/sz+1;
if(bl[i]!=bl[i-1]) L[bl[i]]=i,R[bl[i-1]]=i-1;
}
R[bl[n]]=n;
build();
while(m--){
int op=read(),x=read(),y=read();
if(op==1) update(x,y);
else printf("%lld\n",query(x,y));
}
}

浙公网安备 33010602011771号