您的位置:首页 > 其它

Educational Codeforces Round 37 F. SUM and REPLACE 线段树区间更新及查询

2018-02-05 00:03 363 查看
题意:

给定一段区间(值最大1e6),长度最大3e5;

给定两种操作,1更新:修改【l,r】的值,把这个数改成这个数的因子的个数;2查询:输出【l,r】之间的和;

思路:

开始没敢想暴力修改,后来发现,所有数的值在经过修改之后都会变得很小,几次修改变成2之后,就不会改变了;

这样就可以用线段树维护区间最大值以及区间和;当区间最大值小于等于2时,这段区间就不用更新了(题眼吧);

#include<iostream>
#include<algorithm>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<list>
#include<stack>
#include<map>
#pragma comment(linker, "/STACK:102400000,102400000")
#define PI acos(-1.0)
#define in freopen("in.txt", "r", stdin)
#define out freopen("out.txt", "w", stdout)
#define kuaidian ios::sync_with_stdio(0);

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + 7, maxd = 1e6 + 7;
const int mod = 1e9 + 7;
const int INF = 0x7f7f7f7f;

int n, m;
int a[maxn], d[maxd];
int mx[maxn<<2];
ll sum[maxn<<2]; // 维护区间最大值,区间和;;暴力修改

void init() {
for(int i = 1; i < maxd; ++i) {
for(int j =i; j < maxd; j += i) {
d[j]++;
}
}
}

void push_up(int id) {
mx[id] = max(mx[id<<1], mx[id<<1|1]);
sum[id] = sum[id<<1] + sum[id<<1|1];
}

void build(int l_, int r_, int id) {
if(l_ == r_) {
mx[id] = sum[id] = a[l_];
return;
}
int mid = (l_ + r_) / 2;
build(l_, mid, (id<<1));
build(mid+1, r_, (id<<1|1));
push_up(id);
}

void update(int ql, int qr, int l, int r, int id) {
if(mx[id] <= 2) return;
if(l == r) {
mx[id] = sum[id] = d[mx[id]];
return;
}
int mid = (l + r) / 2;
if(qr <= mid) {
update(ql, qr, l, mid, id<<1);
}
else if(ql > mid) {
update(ql, qr, mid+1, r, id<<1|1);
}
else {
update(ql, mid, l, mid, id<<1);
update(mid+1, qr, mid+1, r, id<<1|1);
}
push_up(id);
}

ll query(int ql, int qr, int l, int r, int id) {
if(ql == l && qr == r) return sum[id];
int mid = (l + r) / 2;
if(qr <= mid) {
return query(ql, qr, l, mid, id<<1);
}
else if(ql > mid) {
return query(ql, qr, mid+1, r, id<<1|1);
}
else {
return (query(ql, mid, l, mid, id<<1) + query(mid+1, qr, mid+1, r, id<<1|1));
}
}

int main() {
init();
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
build(1, n, 1);
for(int i = 0; i < m; ++i) {
int ty, l, r;
scanf("%d %d %d", &ty, &l, &r);
if(ty == 1) update(l, r, 1, n, 1);
else printf("%lld\n", query(l, r, 1, n, 1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐