最大只有10^12,开6次方就开不了了,所以直接暴力改
我的代码,有注释,可以参考一下
~~求关~~
```cpp
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
struct node
{
int l, r;
ll sumn; // 区间和
bool tag; // "开不了方"标记, 初始设为0
}ST[N << 2];
ll a[N];
int n, m;
inline void push_up(int ind)
{
// 维护区间和
ST[ind].sumn = ST[ind*2].sumn+ST[ind*2+1].sumn;
// 维护"开不了方"标记,左子区间和右子区间都开不了方,
// 它自然也开不了
ST[ind].tag = ST[ind*2].tag && ST[ind*2+1].tag;
}
inline void build(int ind, int l, int r) // 建树
{
ST[ind].l = l;
ST[ind].r = r;
ST[ind].tag = 0;
if(l == r)
{
ST[ind].sumn = a[l];
return;
}
int mid = (l+r)>>1;
build(ind*2, l, mid);
build(ind*2+1, mid+1, r);
push_up(ind);
}
inline void upd(int ind, int tl, int tr) // update函数
{
if(ST[ind].tag) return; // 开不了方就没必要搜了
if(tl <= ST[ind].l && ST[ind].r <= tr && ST[ind].l == ST[ind].r) // 搜到要改的单点
{
ST[ind].sumn = sqrt(ST[ind].sumn);
if(ST[ind].sumn <= 1) ST[ind].tag = 1; // 开不了方了
return;
}
int mid = (ST[ind].l+ST[ind].r)>>1;
if(tl <= mid) upd(ind*2, tl, tr);
if(tr > mid) upd(ind*2+1, tl, tr);
push_up(ind);
}
inline ll ask(int ind, int tl, int tr) // 求区间和
{
if(tl <= ST[ind].l && ST[ind].r <= tr) return ST[ind].sumn;
int mid = (ST[ind].l+ST[ind].r)>>1;
ll res = 0;
if(tl <= mid) res += ask(ind*2, tl, tr);
if(tr > mid) res += ask(ind*2+1, tl, tr);
return res;
}
int main()
{
// 建议大家在读入 >= 1e5次的数据是用scanf和printf,比cin,cout快很多
cin >> n;
for(int i = 1;i <= n;++i) scanf("%lld", &a[i]);
build(1, 1, n);
cin >> m;
int k, l, r;
while(m--)
{
scanf("%d%d%d", &k, &l, &r);
if(l > r) swap(l, r);
if(k == 0) upd(1, l, r);
else printf("%lld\n", ask(1, l, r));
}
return 0;
}
```
by piano_pei @ 2024-08-07 10:55:01