hdu 4027 Can you answer these queries?

深刻理解到读题的重要性。

0 x y 表示对x和y之间的值进行开根号,向下取整。

1 x y 为求和操作,N属于[1, 1e5]。

因为对元素开根(向下取整),所以每个元素开不了几次,比如2^63次方,log一下最多开7次而已。而1怎么开方都是1,于是如果某一段被开到全都为1,满足g[rt]=r-l+1,那么这段不必更新,以此来节约时间。

还有就是其实是x,y之间的飞船进行开根处理,并没有说x<=y...所以读入后要检查一下。

#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;

#define ll long long
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)

const int maxN=1e5+5;
int N, M, K, T;

#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
ll g[maxN<<2];

void push_up(int rt) {g[rt] = g[rt * 2] + g[rt * 2 + 1];}
void build(int l, int r, int rt) {
    if (l == r) {
        scanf("%lld", &g[rt]);
        return;
    }
    int m = (l + r) / 2;
    build(lson);
    build(rson);
    push_up(rt);
}
void update(int L, int R, int l, int r, int rt) {
    if (g[rt] == r - l + 1) return;
    if (l == r) {
        g[rt] = sqrt(g[rt]);;
        return;
    }
    int m = (l + r) / 2;
    if (L <= m) update(L, R, lson);
    if (R > m) update(L, R, rson);
    push_up(rt);
}
ll query(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) {
        return g[rt];
    }
    int m = (l + r) / 2;
    ll ans = 0;
    if (L <= m) ans += query(L, R, lson);
    if (R > m) ans += query(L, R, rson);
    return ans;
}

int main () {
    int cas = 1;
    while (~scanf("%d", &N)) {
        build(1, N, 1);
        scanf("%d", &M);
        printf("Case #%d:
", cas++);
        int t, a, b;
        FOR(i, 1, M) {
            scanf("%d%d%d", &t, &a, &b);
            if (a > b) swap(a, b);
            if (t == 0) update(a, b, 1, N, 1);
            else printf("%lld
", query(a, b, 1, N, 1));
        }
        puts("");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Rosebud/p/9635410.html