CDOJ 1324 卿学姐与公主 (分块or线段树)

某日,百无聊赖的卿学姐打开了某11区的某魔幻游戏

在这个魔幻的游戏里,生活着一个美丽的公主,但现在公主被关押在了魔王的城堡中。

英勇的卿学姐拔出利刃冲向了拯救公主的道路。

走过了荒野,翻越了高山,跨过了大洋,卿学姐来到了魔王的第一道城关。

在这个城关面前的是魔王的精锐部队,这些士兵成一字排开。

卿学姐的武器每次只能攻击一个士兵,并造成一定伤害,卿学姐想知道某时刻从 L L R R这个区间内,从开始到现在累计受伤最严重的士兵受到的伤害。

最开始每个士兵的受到的伤害都是0

Input

第一行两个整数 N,Q N,Q表示总共有 N N个士兵编号从 1 1 N N,和 Q Q个操作。

接下来 Q Q行,每行三个整数,首先输入一个 t t,如果 t t 1 1,那么输入 p,x p,x,表示卿学姐攻击了 p p这个位置的士兵,并造成了 x x的伤害。如果 t t 2 2,那么输入 L,R L,R,表示卿学姐想知道现在 [L,R] [L,R]闭区间内,受伤最严重的士兵受到的伤害。

1N100000 1≤N≤100000

1Q100000 1≤Q≤100000

1pN 1≤p≤N

1x100000 1≤x≤100000

1LRN 1≤L≤R≤N

Output

对于每个询问,回答相应的值

Sample input and output

Sample Input Sample Output
5 4
2 1 2
1 2 4
1 3 5
2 3 3
0
5


这道题用线段树是可以写出来的就是一个单点更新求最大值的问题
但是这里我们用分块去写,我感觉分块的代码量要比线段树少
#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5+7;

int belong[maxn],block,num,l[maxn],r[maxn],n,q;
long long Max[maxn],a[maxn];

void build()
{
    block = sqrt(n);
    num = n/block;
    if(n%block)num++;
    for(int i = 1;i<=num;i++)
        l[i] =(i-1)*block+1,r[i] = i*block;
    r[num] = n;
    for(int i = 1;i<n;i++)
        belong[i] = (i-1)/block+1;
    for(int i = 1;i<=num;i++)
        for(int j = l[i];j<=r[i];j++)
            Max[i] = max(Max[i],a[i]);
}
void update(int x,int y)
{
    a[x]+=y;
    Max[belong[x]] = max(Max[belong[x]],a[x]);
}
long long ask(int x,int y)
{
    long long ans = 0;
    if(belong[x] == belong[y])//当x y在一个块中
    {
        for(int i = x;i<=y;i++)
            ans = max(a[i],ans);
        return ans;
    }
    for(int i = x;i<=r[belong[x]];i++)//当X Y 不在一个块中
        ans = max(ans,a[i]);
    for(int i = belong[x]+1;i<belong[y];i++)
        ans = max(ans,Max[i]);
    for(int i = belong[y];i<=y;i++)
        ans = max(ans,a[i]);
    return ans;
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i = 0;i < q;i++)
    {
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if(op == 1)update(l,r);
        else printf("%lld\n",ask(l,r));
    }
    return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值