您的位置:首页 > 其它

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

2014-08-21 17:59 274 查看
题意:给出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
, cnt
;
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));
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: