分块算法

本文介绍了一个关于数据结构的问题——卿学姐与公主。玩家需要通过一系列操作来确定区间内受伤害最严重的士兵。涉及离线查询、分块等算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

cdoj 卿学姐与公主

https://acm.uestc.edu.cn/problem/qing-xue-jie-yu-gong-zhu/description/

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

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

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

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

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

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

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

Standard Input

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

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

1\le N \le 1000001≤N≤100000

1\le Q \le 1000001≤Q≤100000

1\le p \le N1≤p≤N

1\le x \le 1000001≤x≤100000

1\le L \le R \le N1≤L≤R≤N

Standard Output

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

Samples

InputOutput
5 4
2 1 2
1 2 4
1 3 5
2 3 3
0
5

Note

注意可能会爆int哦

Problem ID1324
Problem Title卿学姐与公主
Time Limit1000 ms
Memory Limit64 MiB
Output Limit64 MiB
Source2016 UESTC Training for Data Structures

 

卿学姐讲课也太好了叭,爱上了爱上了 ,嘤嘤嘤

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1<<20;//异或值可能比最大值大
int n,m,block,num;
ll a[maxn],Max[maxn],l[maxn],r[maxn],belong[maxn];
void build()
{
    block=sqrt(n);//块大小
    num=n/block;if(n%block)num++;//块数目,如果不能整除 则右边有剩下的,所以num+1
    for(int i=1;i<=n;i++)
        l[i]=(i-1)*block+1,r[i]=i*block;//边界是哪个块
    for(int i=1;i<=n;i++)
        belong[i]=(i-1)/block+1;//每个i属于那个块

    for(int i=1;i<=n;i++)
        for(int j=1;j<=num;j++)
            Max[i]=max(Max[i],a[j]);//每个块内的最大值

}

void update(int x,int y)
{
    a[x]+=y;
    Max[x]=max(Max[x],a[x]);
}

ll ask(int x,int y)
{
    ll ans=0;
    if(belong[x]==belong[y])//如果在一个块内,可以暴力枚举
        for(int i=x;i<=y;i++)
            ans=max(ans,a[i]);
    else
    {
        for(int i=x;i<=r[belong[x]];i++)//[ x,r[x] ]
            ans=max(ans,a[i]);
        for(int i=belong[x]+1;i<belong[y];i++) //[x的下一个块,y的上一个块)
            ans=max(ans,Max[i]);
        for(int i=l[belong[y]];i<=y;i++)//[ l[y],y ]
            ans=max(ans,a[i]);
    }
    return ans;
}


int main()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if(op==1)
            update(l,r);
        else
            cout<<ask(l,r)<<endl;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值