當時在火車上思考的, 思考了半天突然發現了開方操作不是平方操作, 開多了就成1了
然後我發現這樣就可以暴力的去做了, 因爲整個數列最多開6次, 之後就都成了1.
我特別發現數列是沒有零的, 如果沒有0值的話, 一個區間的和如果等於他的長度, 就不需要開深入修改了。
洛谷P4145的數據是沒有零的, libreOj的信息學奧賽一本通提高篇的練習題是有零的。
今天交了幾次, 但是都不對, 我發現數列是有零的, 然後我就有點蒙了。才發現在維護一個區間最大值就可以了。
但還是不對, 最後在一組樣例的幫助下, 我把不再查詢的區間最先return即可。
// 要注意一個區間與另一個區間的關係有三種, 完全包含, 完全不想交, 完全不包含
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
const int MAXN = 1e5 + 600;
typedef long long ll;
using namespace std;
int n, m;
int cmd, ql, qh;
struct Segment{
ll sum, max;
} s[MAXN << 2 | 1];
inline void update(int o){
s[o].sum = s[o << 1].sum + s[o << 1 | 1].sum;
s[o].max = max(s[o << 1].max, s[o << 1 | 1].max);
}
void build(int o, int lo ,int hi){
if(hi - lo < 2){
scanf("%lld", &s[o].sum);
s[o].max = s[o].sum;
return;
}
int mi = (lo + hi) >> 1;
build(o << 1, lo, mi);
build(o << 1 | 1, mi, hi);
update(o);
}
void modify(int o, int lo, int hi){
if(qh <= lo || hi <= ql){// 最先判斷
return;
}
if(hi - lo < 2){
s[o].sum = (ll)(floor(sqrt(s[o].sum)));
s[o].max = s[o].sum;
return;
}
if(ql <= lo && hi <= qh){
if(s[o].max < 2){
return;
}
}
int mi = (lo + hi) >> 1;
modify(o << 1, lo, mi);
modify(o << 1 | 1, mi, hi);
update(o);
}
ll query(int o, int lo, int hi){
if(ql <= lo && hi <= qh){
return s[o].sum;
}
if(qh <= lo || hi <= ql){
return 0;
}
int mi = (lo + hi) >> 1;
ll rst = query(o << 1, lo, mi) + query(o << 1 | 1, mi, hi);
return rst;
}
void print(int o, int lo, int hi){
if(hi - lo < 2){
printf(" %lld", s[o].sum);
return;
}
int mi = (lo + hi) >> 1;
print(o << 1, lo, mi);
print(o << 1 | 1, mi, hi);
}
int main(){
scanf("%d", &n);
build(1, 1, ++n);
scanf("%d", &m);
// print(1, 1, n); puts("\tOUT");
while(m--){
scanf("%d%d%d", &cmd, &ql, &qh);
if(ql > qh){
swap(ql, qh);
}
++qh;
if(cmd == 1){
printf("%lld\n", query(1, 1, n));
}
else{
modify(1, 1, n);
}
// print(1, 1, n); puts("\tOUT");
}
return 0;
}