您的位置:首页 > 其它

Educational Codeforces Round 37 (Rated for Div. 2)-F-SUM and REPLACE(线段树)

2018-02-05 23:07 489 查看


题意:给你一个长为n的序列,m个查询,有两种操作

(1)将区间[l,r]内的每个数的值变为该数的因子个数

(2)查询区间[l,r]所有值的和

题解:乍一看感觉线段树会超时,因为区间更新用到的懒惰数组无法维护,但是仔细想想,其实一个数不会更新很多次,这让我联想到了之前打的一场喵哈哈村有道题是每次将一个区间的所有数开平方根,和这道题几乎一模一样,我们知道当一个数更新到小于等于2时就没必要再给他更新了,因为他都不会变,所以我们记一下区间最大值即可。。。。。只要这个区间的最大值小于等于2,则该区间就不用更新,所以总得下来因为值只会变小,所以不会更新很多次,因此这道题就是个裸的线段树。。

#include<stdio.h>
#include<algorithm>
using namespace std;
#define maxn 3000005
#define ll long long
ll sum[maxn],mx[maxn],a[maxn],d[maxn];
void build(int id,int l,int r)
{
if(l==r)
{
scanf("%lld",&a[id]);
sum[id]=mx[id]=a[id];
return;
}
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
mx[id]=max(mx[id*2],mx[id*2+1]);
sum[id]=sum[id*2]+sum[id*2+1];
}
void update(int id,int l,int r,int L,int R)
{
if(mx[id]<=2) return;
if(l==r)
{
mx[id]=sum[id]=d[mx[id]];
return;
}
int mid=(l+r)/2;
if(L<=mid)
update(id*2,l,mid,L,R);
if(R>mid)
update(id*2+1,mid+1,r,L,R);
mx[id]=max(mx[id*2],mx[id*2+1]);
sum[id]=sum[id*2]+sum[id*2+1];
}
ll query(int id,int l,int r,int L,int R)
{
if(L<=l && R>=r)
return sum[id];
ll mid=(l+r)/2,res=0;
if(L<=mid)
res+=query(id*2,l,mid,L,R);
if(R>mid)
res+=query(id*2+1,mid+1,r,L,R);
return res;
}
int main(void)
{
int n,m,t,x,y;
for(int i=1;i<=1000000;i++)
for(int j=i;j<=1000000;j+=i)
d[j]++;
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--)
{
scanf("%d%d%d",&t,&x,&y);
if(t==1)
update(1,1,n,x,y);
else
printf("%lld\n",query(1,1,n,x,y));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐