思路:暴力开根号,全为1的块打上标记
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m;
const int N = 1e5 + 7;
ll a[N],ed[N],st[N],pos[N],block,t,tag[N];
void build()
{
block = sqrt(n);
t = n / block;
if (n % block)t++;
for (int i = 1;i <= t;i++)
{
st[i] = (i - 1) * block + 1;
ed[i] = block * i;
}
for (int i = 1;i <= n;i++)
{
pos[i] = (i - 1) / block + 1;
}
}
void sq(int l, int r)
{
ll p = pos[l], q = pos[r];
if (p == q)
{
for (int i = l;i <= r;i++)a[i] = sqrt(a[i]);
}
else
{
for (int i = l;i <= ed[p];i++)a[i] = sqrt(a[i]);
for (int i = st[q];i <= r;i++)a[i] = sqrt(a[i]);
for (int i = p + 1;i <= q - 1;i++)
{
if (tag[i])continue;
int cnt = 0;
for (int j = st[i];j <= ed[i];j++)
{
a[j] = sqrt(a[j]);
if (a[j] == 1)cnt++;
if (cnt == ed[i] - st[i] + 1)tag[i] = 1;
}
}
}
}
void query(int l, int r)
{
ll ans = 0;
ll p = pos[l], q = pos[r];
if (p == q)
{
for (int i = l;i <= r;i++)ans += a[i];
}
else
{
for (int i = l;i <= ed[p];i++)ans += a[i];
for (int i = st[q];i <= r;i++)ans += a[i];
for (int i = p + 1;i <= q - 1;i++)
{
if (tag[i])ans += ed[i] - st[i] + 1;
else
{
for (int j = st[i];j <= ed[i];j++)ans += a[j];
}
}
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> n;
for (int i = 1;i <= n;i++)cin >> a[i];
build();
cin >> m;
while (m--)
{
int op,l,r;
cin >> op >> l >> r;
if (l > r)swap(l, r);
if (op == 0)
{
sq(l, r);
}
else
{
query(l, r);
}
}
return 0;
}