HDU - 6315 Naive Operations 线段树(多校2-1007)

题意:

给定序列a,b;a初始值为0,b是1-n的排列;

每次对a序列操作:

add L R操作是给a序列 区间【L-R】每个值+1;

query L R操作是对区间【L-R】对应的 [a[i] / b[i]](向下取整) 求和;

思路:

令ans[i] = a[i] / b[i] (向下取整), 首先可以想到,要使ans[i]加一的话,a[i]需要加 b[i] ,这样每时每刻都会存在一个最小的t[i] ,使得a[i]+t[i] 能令ans[i]  +1,也就是我代码中维护的min_[] 值,会随着对a[]数组更新而减小

我们要维护的就是这个min_[]值,还要进行一下线段树的lazy操作(即我代码中的add[]数组),如果min[i]为负数,意味着这个区间有个子区间可以满足使ans[i] +1;继续往下更新或查询;

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;
const int maxn = 100010;
typedef long long ll;
int n, q;
int b[maxn];
int min_[maxn<<2];
ll sum[maxn<<2];
int add[maxn<<2];

void push_up(int id) {
    min_[id] = min(min_[id<<1], min_[(id<<1|1)]);
    sum[id] = sum[id<<1] + sum[(id<<1)|1];
}
void build(int id, int l_, int r_) {
    sum[id] = 0;
    add[id] = 0;
    if(l_ == r_) {
        min_[id] = b[l_];
        return;
    }
    int mid = (l_ + r_) >> 1;
    build(id<<1, l_, mid);
    build((id<<1)|1, mid+1, r_);
    push_up(id);
}
void push_down(int id, int num) {
    add[id<<1] += num;
    add[(id<<1)|1] += num;
    min_[id<<1] -= num;
    min_[(id<<1)|1] -= num;
    add[id] = 0;
}
void update(int id, int l_, int r_, int ul, int ur) {
    if(ul > r_ || ur < l_)
        return;
    if(ul == l_ && ur == r_) {
        add[id] += 1;
        min_[id] -= 1;
        return;
    }
    push_down(id, add[id]);
    int mid = (l_ + r_) / 2;
    if(ul > mid) {
        update((id<<1)|1, mid+1, r_, ul, ur);
    } else if(ur <= mid) {
        update((id<<1), l_, mid, ul, ur);
    } else {
        update((id<<1), l_, mid, ul, mid);
        update((id<<1)|1, mid+1, r_, mid+1, ur);
    }
    push_up(id);
}


void query(int id, int l_, int r_) {
    if(l_ == r_) {
        if(min_[id] > 0)
            return;
        int t = add[id] / b[l_];
        add[id] %= b[l_];
        sum[id] += t;
        min_[id] = b[l_] - add[id];
        return;
    }

    if(min_[id] > 0) return;
    push_down(id, add[id]);
    int mid = (l_ + r_) / 2;
    query(id<<1, l_, mid);
    query((id<<1)|1, mid+1, r_);
    push_up(id);
}
ll query1(int id, int l_, int r_, int ql, int qr) {
    if(ql > r_ || qr < l_)
        return 0;
    if(ql == l_ && qr == r_) {
        return sum[id];
    }
    //int res = 0;
    int mid = (l_ + r_) >> 1;
    if(ql > mid) {
        return query1((id<<1)|1, mid+1, r_, ql, qr);
    } else if(qr <= mid) {
        return query1(id<<1, l_, mid, ql, qr);
    } else {
        return query1(id<<1, l_, mid, ql, mid) + query1((id<<1)|1, mid+1, r_, mid+1, qr);
    }
}
int main() {
    while(~scanf("%d%d", &n, &q)) {
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &b[i]);
        }
        build(1, 1, n);
        char s[17];
        int L, R;
        int f = 0;
        for(int i = 0; i < q; ++i) {
            scanf("%s", s);
            if(s[0] == 'a') {
                scanf("%d%d", &L, &R);
                update(1,1,n,L,R);
                f = 1;
            } else if(s[0] == 'q') {
                scanf("%d%d", &L, &R);
                if(f)
                    query(1, 1, n);
                f = 0;
                ll anss = query1(1, 1, n, L, R);
                printf("%lld\n", anss);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiang_6/article/details/81214166