CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)
Posted garrettwale
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)相关的知识,希望对你有一定的参考价值。
除法
201709-5
- 这道题有很多种方法来做,最常用的就是线段树和树状数组。
- 如果使用线段树来做,就会想到区间修改的update函数。但是这里可能会涉及到v是1或者a[j]是0的情况,所以用这种方法会超时,最多50分。
- 可以修改一下代码,使用点修改来做这道题。在main函数里面增加一个循环,用来判断。
- 当然,还有一种方法就是树状数组,这种方法和上面这种方法运行时间相差无几,但是代码量大大减少。
- 需要注意的是,如果v是long long型,最好不要用scanf %lld的方式读入,否则超时。
使用线段树代码:
//线段树求解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100005;
int n,m;
int a[maxn];
long long sum[maxn<<2];
void pushup(int id,int l,int r)
int lc=id<<1;
int rc=id<<1|1;
sum[id]=sum[lc]+sum[rc];
void build(int id,int l,int r)
if(l==r)
sum[id]=a[l];
return;
int mid=(l+r)>>1;
int lc=id<<1;
int rc=id<<1|1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(id,l,r);
//---------------------------区间修改
// void update(int id,int l,int r,int p,int q,int v)
// if(l==r)
// if(sum[id]>=v&&sum[id]%v==0)
// sum[id]/=v;
// return;
//
// int mid=(l+r)>>1;
// if(p<=mid)
// update(id<<1,l,mid,p,q,v);
//
// if(q>mid)
// update(id<<1|1,mid+1,r,p,q,v);
//
// pushup(id,l,r);
//
//-------------------------------点修改
void update(int id,int l,int r,int p)
if(l==r)
sum[id]=a[p];
return;
int mid=(l+r)>>1;
if(p<=mid)
update(id<<1,l,mid,p);
if(p>mid)
update(id<<1|1,mid+1,r,p);
pushup(id,l,r);
long long query(int id,int l,int r,int p,int q)
long long sums=0;
if(p<=l&&q>=r)
return sum[id];
int mid=(l+r)>>1;
if(p<=mid)
sums+=query(id<<1,l,mid,p,q);
if(q>mid)
sums+=query(id<<1|1,mid+1,r,p,q);
return sums;
int main()
// ios::sync_with_stdio(false);
// cin.tie(0);
scanf("%d%d",&n,&m);
//cin>>n>>m;
for(int i=1;i<=n;i++)
//cin>>a[i];
scanf("%d",&a[i]);
build(1,1,n);
for(int i=0;i<m;i++)
int opt,p,q;
scanf("%d%d%d",&opt,&p,&q);
//cin>>opt>>p>>q;
if(opt==1)//update
int v;
scanf("%d",&v);
//cout<<v<<endl;
//cin>>v;
//-------------------------------区间修改
// if(v==1)
// continue;
// update(1,1,n,p,q,v);
if(v==1)
continue;
// //--------------------------点修改
for(int j=p;j<=q;j++)
if(a[j]>=v&&a[j]%v==0)
a[j]/=v;
update(1,1,n,j);
else
cout<<query(1,1,n,p,q)<<endl;
//system("pause");
return 0;
使用树状数组代码:
//树状数组求解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100005;
int n,m;
int a[maxn];
long long c[maxn];
int lowbit(int x)
return x&(-x);
long long sum(int x)
long long ret=0;
while(x>0)
ret+=c[x];
x-=lowbit(x);
return ret;
void add(int x,int v)
while(x<=n)
c[x]+=v;
x+=lowbit(x);
int main()
// ios::sync_with_stdio(false);
// cin.tie(0);
//cin>>n>>m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
//cin>>a[i];
scanf("%d",&a[i]);
add(i,a[i]);
for(int i=0;i<m;i++)
int opt;
//cin>>opt;
scanf("%d",&opt);
if(opt==1)
int p,q;int v;
//cin>>p>>q>>v;
scanf("%d%d%d",&p,&q,&v);//这里不能用%lld来读取long long 型,
if(v==1)
continue;
for(int j=p;j<=q;j++)
if(a[j]>=v&&a[j]%v==0)
add(j,a[j]/v-a[j]);
a[j]/=v;
else
int p,q;
//cin>>p>>q;
scanf("%d%d",&p,&q);
cout<<sum(q)-sum(p-1)<<endl;
//system("pause");
return 0;
以上是关于CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)的主要内容,如果未能解决你的问题,请参考以下文章