Description
XLk覺得《上帝造題的七分鐘》不太過癮,於是有了第二部。 “第一分鐘,X說,要有數列,於是便給定了一個正整數數列。
第二分鐘,L說,要能修改,於是便有了對一段數中每個數都開平方(下取整)的操作。 第三分鐘,k說,要能查詢,於是便有了求一段數的和的操作。
第四分鐘,彩虹喵說,要是noip難度,於是便有了數據範圍。 第五分鐘,詩人說,要有韻律,於是便有了時間限制和內存限制。
第六分鐘,和雪說,要省點事,於是便有了保證運算過程中及最終結果均不超過64位有符號整數類型的表示範圍的限制。
第七分鐘,這道題終於造完了,然而,造題的神牛們再也不想寫這道題的程序了。”
——《上帝造題的七分鐘·第二部》
所以這個神聖的任務就交給你了。Input
第一行一個整數n,代表數列中數的個數。
第二行n個正整數,表示初始狀態下數列中的數。
第三行一個整數m,表示有m次操作。
接下來m行每行三個整數k,l,r,k=0表示給[l,r]中的每個數開平方(下取整),k=1表示詢問[l,r]中各個數的和。Output
對於詢問操作,每行輸出一個回答。
Sample Input
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
Sample Output
19
7
6
HINT
1:對於100%的數據,1<=n<=100000,1<=l<=r<=n,數列中的數大於0,且不超過1e12。
2:數據不保證L<=R 若L>R,請自行交換L,R,謝謝!
Source
Poetize4
線段樹區間開根……操作時只需要檢驗一下區間內是否全爲一,若全爲一,則不做操作;否則,單點開根。
不過……論仔細讀題的重要性。注意數據範圍和不保證l <= r!
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
const int SZ = 200010;
struct SGT
{
int l, r;
LL sum;
}tree[SZ << 2];
LL num[200010];
void update(int now)
{
tree[now].sum = tree[now << 1].sum + tree[now << 1 | 1].sum;
return ;
}
void build(int now, int l, int r)
{
tree[now].l = l;
tree[now].r = r;
if(l == r)
{
tree[now].sum = num[l];
return ;
}
int mid = (l + r) >> 1;
build(now << 1, l, mid);
build(now << 1 | 1, mid + 1, r);
update(now);
return ;
}
void C(int now, int l, int r)
{
if(tree[now].l == tree[now].r)
{
tree[now].sum = sqrt(tree[now].sum);
return ;
}
update(now);
int mid = (tree[now].l + tree[now].r) >> 1;
C(now << 1, l, r);
C(now << 1 | 1, l, r);
update(now);
return;
}
void change(int now, int l, int r)
{
if(l <= tree[now].l && tree[now].r <= r)
{
if(tree[now].r - tree[now].l + 1 == tree[now].sum)
return ;
C(now, l, r);
return;
}
update(now);
int mid = (tree[now].l + tree[now].r) >> 1;
if(l <= mid) change(now << 1, l, r);
if(r > mid) change(now << 1 | 1, l, r);
update(now);
}
LL Ask(int now, int l, int r)
{
if(l <= tree[now].l && tree[now].r <= r)
return tree[now].sum;
update(now);
int mid = (tree[now].l + tree[now].r) >> 1;
LL ans = 0;
if(l <= mid) ans += Ask(now << 1, l, r);
if(r > mid) ans += Ask(now << 1 | 1, l, r);
return ans;
}
int main()
{
int n, m;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%lld", &num[i]);
build(1, 1, n);
scanf("%d", &m);
int op, l, r;
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &op, &l, &r);
if(l > r) swap(l, r);
if(op == 1) printf("%lld\n", Ask(1, l, r));
else change(1, l, r);
}
return 0;
}