BZOJ 3038 上帝造題的七分鐘2

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;
}
發佈了62 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章