[BZOJ3211]花神游历各国

花神游历各国

Description
这里写图片描述
Input
这里写图片描述
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
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9

Solution
一个数最多只能开方loglog次,所以暴力开方,统计该区间是否还需要修改。

Code

#include <bits/stdc++.h>
using namespace std;

#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define MS(_) memset(_, 0, sizeof(_))
#define PB push_back
#define MP make_pair
#define debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long ll;
typedef pair<int, int> PII;
template<typename T> inline void read(T &x){
    x = 0; T f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch))  {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}

const int N = 100000+100;
struct Node{
    int l, r, need; ll sum;
    Node *lc, *rc;
    inline void push_up(){
        sum = lc->sum + rc->sum;
        need = lc->need | rc->need;
    }   
}pool[N<<2], *tail = pool, *root = pool;
int n, m;
ll a[N];

inline void build(Node *(&rt), int l, int r){
    rt = tail++; rt->l = l; rt->r = r;
    if (l == r) { rt->sum = a[l]; rt->need = (a[l]!=0 && a[l]!=1); return; }
    int mid = l+r >> 1;
    build(rt->lc, l, mid);
    build(rt->rc, mid+1, r);
    rt->push_up();
}
inline void modify(Node *rt, int l, int r){
    if (!rt->need) return;
    if (rt->l == rt->r) {
        rt->sum = (int)sqrt(rt->sum);
        if (rt->sum <= 1) rt->need = 0;
        return;
    }
    int mid = rt->l+rt->r >> 1;
    if (l <= mid) modify(rt->lc, l, r);
    if (r > mid) modify(rt->rc, l, r);
    rt->push_up();
}
inline ll query(Node *rt, int l, int r){ ll res = 0;
    if (l <= rt->l && rt->r <= r) return rt->sum; 
    int mid = rt->l+rt->r >> 1;
    if (l <= mid) res += query(rt->lc, l, r);
    if (r > mid) res += query(rt->rc, l, r);
    return res;
}
int main(){
    read(n);
    rep(i, 1, n) read(a[i]);
    build(root, 1, n);

    read(m);
    while (m--){ int k, l, r;
        read(k); read(l); read(r); if (l > r) swap(l, r);
        if (k == 2) modify(root, l, r); 
        else printf("%lld\n", query(root, l, r));
    }
    return 0;   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值