BZOJ 3211 花神游历各国

Description

1(16).jpg

Input

2(5).jpg

Output

每次x=1时,每行一个整数,表示这次旅行的开心度

Sample Input

4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4

Sample Output

101
11
11

题解

本题和上帝造题的七分钟是一样的

但我的程序没有过啊
打的比较傻

其实只要维护一个值就可以了

用一个flag标记是否不变

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#ifndef LL
#define LL long long
#endif
#define lch l, m, rt << 1
#define rch m + 1, r, rt << 1 | 1
const int N = 100005;
LL Sum[N << 2];
bool flag[N << 2];
void PushUp(int rt)
{
    Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1];
    flag[rt] = flag[rt << 1] & flag[rt << 1 | 1];
}
void buildtree(int l, int r, int rt)
{
    if(l == r)
    {
        scanf("%lld", &Sum[rt]);
        if(Sum[rt] <= 1)
            flag[rt] = 1;
        return;
    }
    int m = l + r >> 1;
    buildtree(lch);
    buildtree(rch);
    PushUp(rt);
}
void Update(int L, int R, int l, int r, int rt)
{
    if(flag[rt])
        return;
    if(l == r)
    {
        Sum[rt] = sqrt(Sum[rt]);
        if(Sum[rt] <= 1)
            flag[rt] = 1;
        return;
    }
    int m = l + r >> 1;
    if (L <= m) Update(L, R, lch);
    if (R > m) Update(L, R, rch);
    PushUp(rt);
}
LL Query(int L, int R, int l, int r, int rt)
{
    if(L <= l && R >= r)
        return Sum[rt];
    int m = l + r >> 1;
    LL ans = 0;
    if (L <= m) ans += Query(L, R, lch);
    if (R > m) ans += Query(L, R, rch);
    return ans;
}
int main()
{
    int n;
    scanf("%d", &n);
    buildtree(1, n, 1);
    int m;
    scanf("%d", &m);
    while (m--)
    {
        int op, l, r;
        scanf("%d%d%d", &op, &l, &r);
        if(l > r)
            swap(l, r);
        if (op == 1)
        {
            printf("%lld\n", Query(l, r, 1, n, 1));
        }
        else
            Update(l, r, 1, n, 1);
    }
}
本文作者 : NekoMio
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
本文链接 : https://www.nekomio.com/2017/09/19/109/
上一篇
下一篇