【HDU 4973 多校联合】A simple simulation problem【树状数组】

15 篇文章 0 订阅
13 篇文章 0 订阅

题意:给出n个数字,分别是1-n。m次操作,有两种操作Q l r, D l r,1.查询区间【l,r】中最多相同数字的个数。2.把【l,r】中的数字都复制一个,如:1 2 3 -> 1 1 2 2 3 3

思路:我们利用cnt[i]数组记录数列中i的个数,然后用树状数组记录前缀和。对于每次Q的操作,我们对于l,r两个端点在前缀和数组中进行二分查找,就可以知道l,r分别是哪个数字,然后通过cnt数字就可以知道落在这个区间中的数目,相应的D操作也是这样子,进行增加个数。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define N 50004
typedef long long ll;

ll sum[N], cnt[N];
int n, m;

int lb(int k) {return k&(-k);}

ll getsum(int k) {
    ll re = 0;
    while (k > 0) {
        re += sum[k];
        k -= lb(k);
    }
    return re;
}

void add(int k, ll v) {
    while (k <= n) {
        sum[k] += v;
        k += lb(k);
    }
}

int find(ll v) {
    int f = 1, r = n, mid;
    ll tm;
    while (f < r) {
        mid = f+r>>1;
        ll tm = getsum(mid);
        if (tm < v) f = mid+1;
        else r = mid;
    }
    return f;
}

void update(ll l, ll r) {
    int i, L = find(l), R = find(r);
    if (L == R) {
        add(L, r-l+1);
        cnt[L] += r-l+1;
        return;
    }
    ll tm = getsum(L), tp = getsum(R-1)  ;
    add(L, tm-l+1), add(R, r-tp);
    cnt[L] += tm-l+1;cnt[R] += r-tp;
    for (i = L+1;i < R;i++) {
        add(i, cnt[i]);
        cnt[i] += cnt[i];
    }
}

ll cal(ll l, ll r) {
    int i, L = find(l), R = find(r);
    ll tm, re = 0, tl = l, tp;
    if (L == R) return r-l+1;
    re = max(re, getsum(L)-l+1);
    re = max(re, r-getsum(R-1));
    for (i = L+1;i < R;i++) {
        if (re < cnt[i]) re = cnt[i];
    }
    return re;
}

int main() {
    int T, ca = 1, i;
    char op;
    ll l, r;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        for (i = 0;i <= n;i++) sum[i] = cnt[i] = 0;
        for (i = 1;i <= n;i++) add(i, 1), cnt[i] = 1;
        printf("Case #%d:\n", ca++);
        while (m--) {
            scanf(" %c%I64d%I64d", &op, &l, &r);
            if (op == 'D') {
                update(l, r);
            }else {
                printf("%I64d\n", cal(l, r));
            }
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值