[BZOJ3038]上帝造题的七分钟2

3038: 上帝造题的七分钟2

Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 1532  Solved: 657 [Submit][Status][Discuss]

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,谢谢!

 
考虑到开方数字下降得非常快,并且除了开方没有其它修改,那么每次开方暴力开就行了,维护一个Max和sum,当然区间最大值等于$1$了就没必要往下走了,那么询问是$O(log(n))$的,修改是均摊$O(1)$的(听说还能用并查集做??)
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
char buf[10000000], *ptr = buf - 1;
inline ll readll(){
    ll n = 0;
    char ch = *++ptr;
    while(ch < '0' || ch > '9') ch = *++ptr;
    while(ch <= '9' && ch >= '0'){
        n = (n << 1) + (n << 3) + ch - '0';
        ch = *++ptr;
    }
    return n;
}
inline int readint(){
    int n = 0;
    char ch = *++ptr;
    while(ch < '0' || ch > '9') ch = *++ptr;
    while(ch <= '9' && ch >= '0'){
        n = (n << 1) + (n << 3) + ch - '0';
        ch = *++ptr;
    }
    return n;    
}
const int maxn = 100000 + 10;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
ll Max[maxn << 2], sum[maxn << 2];
void inline PushUp(int rt){
    Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void Build(int l, int r, int rt){
    if(l == r) sum[rt] = Max[rt] = readll();
    else{
        int mid = l + r >> 1;
        Build(lson);
        Build(rson);
        PushUp(rt);
    }
}
int ql, qr;
void Update(int l, int r, int rt){
    if(l == r){
        sum[rt] = sqrt(sum[rt]);
        Max[rt] = sqrt(Max[rt]);
    }
    else{
        int mid = l + r >> 1;
        if(ql <= mid && Max[rt << 1] > 1) Update(lson);
        if(qr > mid && Max[rt << 1 | 1] > 1) Update(rson);
        PushUp(rt);
    }
}
ll Query(int l, int r, int rt){
    if(ql <= l && r <= qr) return sum[rt];
    else{
        int mid = l + r >> 1;
        ll ret = 0;
        if(ql <= mid) ret += Query(lson);
        if(qr > mid) ret += Query(rson);
        return ret;
    }
}
int main(){
    fread(buf, sizeof(char), sizeof(buf), stdin);
    int n = readint();
    Build(1, n, 1);
    int m = readint(), opt;
    for(int i = 1; i <= m; i++){
        opt = readint();
        ql = readint();
        qr = readint();
        if(ql > qr) swap(ql, qr);
        if(opt == 0) Update(1, n, 1);
        else printf("%lld\n", Query(1, n, 1));
    }
    return 0;
}

 

 
posted @ 2017-09-07 21:31  Elder_Giang  阅读(142)  评论(0编辑  收藏  举报