Description
花神喜欢步行游历各国,顺便虐爆各地竞赛。花神有一条游览路线,它是线型的,也就是说,所有游历国家呈一条线的形状排列,花神对每个国家都有一个喜欢程度(当然花神并不一定喜欢所有国家)。 每一次旅行中,花神会选择一条旅游路线,它在那一串国家中是连续的一段,这次旅行带来的开心值是这些国家的喜欢度的总和,当然花神对这些国家的喜欢程序并不是恒定的,有时会突然对某些国家产生反感,使他对这些国家的喜欢度由t 变为sqrt(t), (可能是花神虐爆了那些国家的 OI,从而感到乏味)。现在给出花神每次的旅行路线,以及开心度的变化,请求出花神每次旅行的开心值。
Input
一行是一个整数 N,表示有 N 个国家; 第二行有 N 个空格隔开的整数,表示每个国家的初始喜欢度ti 第三行是一个整数 M,表示有 M 条信息要处理; 第四行到最后,每行三个整数 x,l,r,当 x=1 时询问游历国家 l 到 r 的开心值总和,当 x=2 时国家 l 到 r 中每个国家的喜欢度由ti变成sqrt(ti);
Output
每次 x=1 时,每行一个整数。表示这次旅行的开心度。
Sample Input
4 1 100 5 5 5 1 1 2 2 1 2 1 1 2 2 2 3 1 1 4
Sample Output
101 11 11
思路:
一般对于区间加乘操作,可以用lazy标记,但像这样对每个数取根号,除去一个整数,并且不增加数的大小,由于对每个数操作次数不会太高,所以可以对每个数单独操作,再加上一个数组标记,当一个区间都不必再操作,就直接return即可。
代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
const int N = 1e5 + 10;
#define ls (o<<1)
#define rs (o<<1|1)
long long sum[N << 2];
long long aa[N << 2];
bool bb[N << 2];//
int k, a, b, m, c, n, x;
long long p;
void build(int o, int l, int r)
{
if (l == r)
{
sum[o] = aa[l];
if (sum[o] == 1 || sum[o] == 0)
bb[o] = 1;
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
sum[o] = sum[ls] + sum[rs];
}
void change(int o, int l, int r, int ql, int qr)
{
if (l == r)
{
sum[o] = (long long)sqrt(sum[o]);
if (sum[o] == 1 || sum[o] == 0)
bb[o] = 1;
return;
}
int mid = (l + r) >> 1;
if (ql <= mid && bb[ls] == 0)
change(ls, l, mid, ql, qr);
if (mid + 1 <= qr && bb[rs] == 0)
change(rs, mid + 1, r, ql, qr);
sum[o] = sum[ls] + sum[rs];
if (bb[ls] && bb[rs])//当区间都不在用取根号时就标记
bb[o] = 1;
}
long long ask(int o, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
return sum[o];
int mid = (l + r) >> 1;
long long ans = 0;
if (ql <= mid)
ans = ans + ask(ls, l, mid, ql, qr);
if (mid + 1 <= qr)
ans = ans + ask(rs, mid + 1, r, ql, qr);
return ans;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%lld", &aa[i]);
build(1, 1, n);
cin >> m;
for (int i = 1; i <= m; i++)
{
int y;
scanf("%d", &y);
if (y == 1)
{
scanf("%d%d", &a, &b);
printf("%lld\n", ask(1, 1, n, a, b));
}
else
{
scanf("%d%d", &a, &b);
change(1, 1, n, a, b);
}
}
return 0;
}