hdu 4973

題意:

給你n個細胞, 分別爲1到n, 執行兩種操作

  1 查詢l, r區間同一種細胞的最大數目 

  2 更新:將l, r區間的細胞複製一遍

分析:

 區間更新和區間查詢明顯是線段樹的題目, 比賽的時候卻因爲區間長度會變化而不知道怎麼做了, 其實同一種細胞總是相鄰的, 所以可以根據查詢的區間求得細胞的類型範圍

對於更新操作, 對類型的兩個端點進行單點更新,中間進行成段更新

對於查詢操作, 分別求兩個端點的長度和中間的長度, 去最大值即可


#include 
#include 
#include 
using namespace std;

typedef long long ll;
ll maxn[50010 << 2], sum[50010 << 2], lazy[50010 << 2];
ll lx, rx, k;
int n, m, x, ql, qr;

void pushUp(int o) {
    maxn[o] = max(maxn[2 * o], maxn[2 * o + 1]);
    sum[o] = sum[2 * o] + sum[2 * o + 1];
}
void pushDown(int o) {
   lazy[2 * o] += lazy[o];
   lazy[2 * o + 1] += lazy[o];
   sum[2 * o] <<= lazy[o];
   sum[2 * o + 1] <<= lazy[o];
   maxn[2 * o] <<= lazy[o];
   maxn[2 * o + 1] <<= lazy[o];
   lazy[o] = 0;
}
void construct(int o, int l, int r) {
    lazy[o] = 0;
    if (l == r) {
        maxn[o] = sum[o] = 1;
        return;
    }
    int m = (l + r) >> 1;
    construct(2 * o, l, m);
    construct(2 * o + 1, m + 1, r);
    pushUp(o);
}
int getId(int o, int l, int r, ll x) {
    if (l == r) return l;
    if (lazy[o])  pushDown(o);
    int  m = (l + r) >> 1;
    if (sum[2 * o] >= x) {
        return getId(2 * o, l, m, x);
    }
    else {
        x -= sum[2 * o];
        return getId(2 * o + 1, m + 1, r, x);
    }
}
void update1(int o, int l, int r) {
    if (l == r) {
        sum[o] += k;
        maxn[o] += k;
        return;
    }
    if (lazy[o])  pushDown(o);
    int m = (l + r) >> 1;
    if (x <= m)  update1(2 * o, l, m);
    else update1(2 * o + 1, m + 1, r);
    pushUp(o);
}
void update2(int o, int l, int r) {
    if (ql <= l && qr >= r) {
        sum[o] *= 2;
        maxn[o] *= 2;
        lazy[o] ++;
        return;
    }
    if (lazy[o])  pushDown(o);
    int m = (l + r) >> 1;
    if (ql <= m) update2(2 * o, l, m);
    if (qr > m)  update2(2 * o + 1, m + 1, r);
    pushUp(o);
}
ll querySum(int o, int l, int r) {
    if (ql <= l && qr >= r) return sum[o];
    ll ans = 0;
    if (lazy[o])  pushDown(o);
    int m = (l + r) >> 1;
    if (ql <= m)  ans += querySum(2 * o, l, m);
    if (qr > m)   ans += querySum(2 * o + 1, m + 1, r);
    return ans;
}
ll query(int o, int l, int r) {
    if (ql <= l && qr >= r) return maxn[o];
    if (lazy[o])  pushDown(o);
    int m = (l + r) >> 1;
    ll ans = 0;
    if (ql <= m) ans = max(ans, query(2 * o, l, m));
    if (qr > m)  ans = max(ans, query(2 * o + 1, m + 1, r));
    return ans;
}
int main() {
    int T, ca = 1;
    scanf("%d", &T);
    while (T --) {
        scanf("%d%d", &n, &m);
        construct(1, 1, n);
        printf("Case #%d:\n", ca++);
        while (m --) {
            char s[10];
            scanf("%s%I64d%I64d", s, &lx, &rx);
            int id1 = getId(1, 1, n, lx);
            int id2 = getId(1, 1, n, rx);
            if (s[0] == 'D') {
                if (id1 == id2) {
                    x = id1;
                    k = rx - lx + 1;
                    update1(1, 1, n);
                }
                else {
                    ql = 1, qr = id2 - 1;
                    x = id2;
                    k = rx - querySum(1, 1, n);
                    update1(1, 1, n);
                    ql = 1, qr = id1;
                    x = id1;
                    k = querySum(1, 1, n) - lx + 1;
                    update1(1, 1, n);
                    ql = id1 + 1, qr = id2 - 1;
                    if (ql <= qr)  update2(1, 1, n);
                }
            }
            else {
                if (id1 == id2) {
                    printf("%I64d\n", rx - lx + 1);
                }
                else {
                    ll res = 0;
                    ql = 1, qr = id2 - 1;
                    res = max(res, rx - querySum(1, 1, n));
                    ql = 1, qr = id1;
                    res = max(res, querySum(1, 1, n) - lx + 1);
                    ql = id1 + 1, qr = id2 - 1;
                    if (ql <= qr)  res = max(res, query(1, 1, n));
                    printf("%I64d\n", res);
                }
            }
        }
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章