您的位置:首页 > 其它

hdu 4973 A simple simulation problem. (线段树)

2014-08-26 20:03 363 查看
题目链接

题意:

给定n长的序列 m个操作

序列默认为 1, 2, 3···n

操作1:D [l,r] 把[l,r]区间增长 :( 1,2,3,4 进行 D [1,3]变成 1,1,2,2,3,3,4 )

操作2:Q [l,r] 问区间[l,r] 上出现最多次数的数 的次数

分析:

会线段树,但是做题的时候没想到如何把这个处理,这是问题的关键。

当时比赛的时候卡了一题,然后快结束的时候看的这个题,所以很乱,没有想出来。

赛后, 我自己有写了一遍,但是我很sb的吧中间的一个变量写错了,结果错了好几天。

今天看别人的题解的时候,他们有加了一个lz【】延迟标记的,就是更新的时候更新到一整个区间的时候,就停止。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define LL __int64
#define lson l, mid, 2*rt
#define rson mid+1, r, 2*rt+1
const int maxn = 50000+10;
using namespace std;
LL cnt[4*maxn], mx[4*maxn];

void pushup(LL rt)
{
cnt[rt] = cnt[2*rt]+cnt[2*rt+1];
mx[rt] = max(mx[2*rt], mx[2*rt+1]);
}
void build(LL l, LL r, LL rt)
{
if(l==r)
{
cnt[rt] = 1;
mx[rt] = 1;
return;
}
int mid = (l+r)/2;
build(lson);
build(rson);
pushup(rt);
}
void update(LL ll, LL rr, LL l, LL r, LL rt) //每次更新到底
{
if(l==r)
{
cnt[rt] += (rr-ll+1);
mx[rt] = cnt[rt];
return;
}
int mid = (l+r)/2;
LL tmp = cnt[2*rt];   //就是这个变量写错了,错了好几天
//还有这里一定要提前记录下cnt[2*rt],因为递归以后cnt[2*rt]的值会改变。
if(tmp>=rr)      update(ll, rr, lson);
else if(tmp<ll)  update(ll-tmp, rr-tmp, rson);
else
{
update(ll, tmp, lson);
update(1, rr-tmp, rson);
}
pushup(rt);
}
LL query(LL ll, LL rr, LL l, LL r, LL rt)
{
if(cnt[rt]==(rr-ll+1)) //查找的时候如果发现个数和那个区间的个数相同就是 区间都覆盖了
return mx[rt];
if(l==r)
return (rr-ll+1);

int mid = (l+r)/2;
LL tmp = cnt[2*rt];

if(tmp>=rr) return query(ll, rr, lson);
else if(tmp<ll) return query(ll-tmp, rr-tmp, rson);
else return max(query(ll, tmp, lson), query(1, rr-tmp, rson));
}
int main()
{
int t, ca = 1;
LL n, m;
LL l, r;
char ch;
scanf("%d", &t);
while(t--)
{
memset(mx, 0, sizeof(mx));
memset(cnt, 0, sizeof(cnt));
scanf("%I64d%I64d", &n, &m);
build(1, n, 1);
printf("Case #%d:\n", ca++);
while(m--)
{
getchar();
scanf("%c %I64d %I64d", &ch, &l, &r);
if(ch=='D')
update(l, r, 1, n, 1);
else
printf("%I64d\n", query(l, r, 1, n, 1));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: