【bzoj3211】花神游历各国

其实这是一道sb题……
哦不其实是两道2333333(还有3038也是同一题)
然而在写3038的时候由于数据太水直接就A掉了。。。
刚刚拿之前的code交上去就WA啦。。。
不能判断区间和是否==r-l+1因为会出现0……所以要开多一个东西表示这个区间还有多少个数不会再改变了
每个数可以开方的次数是很小的,就当做是常数非常小的 O(logn)
这样复杂度就是 O(nlog2n)

#include <bits/stdc++.h>
#define lc (u << 1)
#define rc (u << 1 | 1)
#define T int u = 1 , int l = 1 , int r = n
#define L lc , l , m
#define R rc , m + 1 , r
#define rep(i,a,b) for(int i = a;i <= b;i ++)
#define maxn 100007

typedef long long ll;

ll rd() {
    char c = getchar();
    while (!isdigit(c)) c = getchar( ) ; ll x = c - '0';
    while (isdigit(c = getchar())) x = x * 10 + c - '0';
    return x;
}

ll sum[maxn * 4 + 1] , cnt[maxn * 4 + 1] , a[maxn];
ll n , m , ql , qr;

void build(T) {
    if (l == r) 
        { sum[u] = a[l] , cnt[u] = (a[l] <= 1) ; return ; }
    int m = (l + r) >> 1;
    build(L) , build(R);
    sum[u] = sum[lc] + sum[rc];
    cnt[u] = cnt[lc] + cnt[rc];
}

void modi(T) {
    if (cnt[u] == r - l + 1)
        return ;
    if (l == r)
        { sum[u] = (ll)sqrt(sum[u]) , cnt[u] = (sum[u] <= 1) ; return ; }
    int m = (l + r) >> 1;
    if (ql <= m) modi(L);
    if (qr >  m) modi(R);
    sum[u] = sum[lc] + sum[rc];
    cnt[u] = cnt[lc] + cnt[rc];
}

ll que(T) {
    if (ql <= l && r <= qr)
        return sum[u];
    int m = (l + r) >> 1;
    ll ret = 0;
    if (ql <= m) ret += que(L);
    if (qr >  m) ret += que(R);
    return ret;
}

void input() {
    n = rd();
    rep(i , 1 , n) a[i] = rd();
    build();
}

void solve() {
    m = rd();
    rep(i , 1 , m) {
        int k = rd();
        ql = rd() , qr = rd();
        if (ql > qr) std::swap(ql , qr);
        if (k == 1) printf("%lld\n" , que());
        else modi();
    }
}

int main() {
    input();
    solve();
    return 0;
}

你可能感兴趣的:(【bzoj3211】花神游历各国)