F. SUM and REPLACE(線段樹+思維+剪枝)

在這裏插入圖片描述
在這裏插入圖片描述
題目大意:
先定義一個D(i):iD(i):i的因子個數,現在給你一個序列,你要做兩種操作,操作1:[l,r]aid(ai)1:將[l,r]中的ai用d(ai)替換。操作2:2:求區間[l,r][l,r]所有數字和。
思路:
這題與D. The Child and Sequence是一個套路,注意到將d(1e6)d(1e6)1or21 or 2,不會超過1010次(很顯然次數特別少),所以可以可以單點修改,維護一個最大值,當最大值<=2<=2,這個區間可以不管了,因爲d(1)=1,d(2)=2d(1)=1,d(2)=2。所以粗略的估計總複雜度不會超過O(m10logm)O(m10logm)
總結:有點體會到線段樹套路題了。單點修改的時候maxmax也要修改(一開始忘記了。)。
代碼:

#include<iostream>
using namespace std;

typedef long long int ll;
const int maxn = 3e5 + 10;
const int maxx = 1e6 + 10;
int ans[maxx];
struct seg{
	int l,r;
	ll s,m;
	seg(){s = 0,m = 0;}
	seg(int a,int b):l(a),r(b){}
}tree[maxn << 2];
void build(int id,int l,int r){
	tree[id] = {l,r};
	if(l == r){
		scanf("%lld",&tree[id].s);
		tree[id].m = tree[id].s;
		return ;
	}
	int mid = l + r >> 1;
	build(id << 1,l,mid);
	build((id << 1) + 1,mid + 1 ,r);
	tree[id].s = tree[id << 1].s + tree[(id << 1) + 1].s;
	tree[id].m = max(tree[id << 1].m ,tree[(id << 1) + 1].m);
}
ll query(int id,int l,int r){
	if(tree[id].l >= l && tree[id].r <= r){
		return tree[id].s;
	}
	int mid = tree[id].l + tree[id].r >> 1;
	ll ans = 0;
	if(r <= mid)return ans += query(id << 1,l,r);
	else if(l > mid) return ans += query((id << 1) + 1,l,r);
	else return ans += query(id << 1,l,r) + query((id << 1) + 1,l,r);
}
void update(int id,int l,int r){
	if(tree[id].m <= 2)return;
	if(tree[id].l >= l && tree[id].r <= r && tree[id].l == tree[id].r){
		tree[id].m = tree[id].s = ans[tree[id].s];
		return ;
	}
	int mid = tree[id].l + tree[id].r >> 1;
	if(r <= mid) update(id << 1,l,r);
	else if(l > mid) update((id << 1) + 1,l,r);
	else update(id << 1,l,r) ,  update((id << 1) + 1,l,r);
	tree[id].s = tree[id << 1].s + tree[(id << 1) + 1].s;
	tree[id].m = max(tree[id << 1].m ,tree[(id << 1) + 1].m);
}
void solved(){
	for(int i = 1; i <= 1e6; i++){
        for(int j = i; j <= 1e6; j += i)
            ans[j]++;
    }
	int n,m;cin>>n>>m;
	build(1,1,n);
	while(m--){
		int ins,l,r;scanf("%d%d%d",&ins,&l,&r);
		if(ins == 2){
			printf("%lld\n",query(1,l,r));
		}
		if(ins == 1){
			update(1,l,r);
		}
	}
}
int main(){
	solved();
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章