少有的好混分的第五题。
普通数组30分,树状数组50分,至于线段树的区间更新,有大佬教教我吗。
我发现树状数组就能100分,只是需要优化常数。
区间内选择性做除法,似乎只能进行单点更新,如果路过的大佬有更好的方法,求指点!
下面有100分代码,9.937s险胜…大佬如果有更好的优化方法,求告知!
#include
long long a[100005];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int f,l,r,v;
while(m--){
scanf("%d",&f);
if(f==1){
scanf("%d%d%d",&l,&r,&v);
for(int i=l;i<=r;i++){
if(a[i]%v==0)
a[i]/=v;
}
} else {
scanf("%d%d",&l,&r);
int ans=0;
for(int i=l;i<=r;i++) ans+=a[i];
printf("%d\n",ans);
}
}
return 0;
}
#include
long long a[100005],c[100005]={0};
int n,m;
void update(int i,long long k){//更新树状数组
while(i<=n){
c[i]+=k;
i+=i&(-i);//lowbit运算
}
}
long long getsum(int r){//求区间1——r的和
long long res=0;
while(r>0){
res+=c[r];
r-=r&(-r);
}
return res;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
update(i,a[i]);
}
int f,l,r,v;
while(m--){
scanf("%d",&f);
if(f==1){//操作1
scanf("%d%d%d",&l,&r,&v);
for(int i=l;i<=r;i++){
if(a[i]%v==0){//进行单点更新
update(i,a[i]/v-a[i]);
a[i]/=v;
}
}
}
else{//操作2
scanf("%d%d",&l,&r);
long long ans=getsum(r)-getsum(l-1);
printf("%lld\n",ans);
}
}
return 0;
}
100分代码如下
#include
#include
long long a[100005],c[100005]={0};
int n,m;
long long read(){//读优化,没有这个90分
long long x=0,f=1;
char c=getchar();//scanf函数比getchar函数慢不少,当需要大量输入数据时可考虑优化
while(c>'9'||c<'0'){
if(c=='-') f=-f;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
void update(int i,long long k){
while(i<=n){
c[i]+=k;
i+=i&(-i);
}
}
long long getsum(int r){
long long res=0;
while(r>0){
res+=c[r];
r-=r&(-r);
}
return res;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)
update(i,a[i]=read());
int f,l,r,v;
while(m--){
if(read()==1){
l=read(),r=read(),v=read();
if(v==1) continue;//这个能省很多时间
for(int i=l;i<=r;++i){
if(a[i]>=v&&a[i]%v==0){//加第一个条件也能省时间
long long temp=a[i];
a[i]/=v;
update(i,a[i]-temp);
}
}
}
else{
l=read(),r=read();
printf("%lld\n",getsum(r)-getsum(l-1));
}
}
return 0;
}