cdoj1324——分块入门

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

Description

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

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

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

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

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

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

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

Standard Input

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

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

1≤N≤1000001\le N \le 1000001≤N≤100000

1≤Q≤1000001\le Q \le 1000001≤Q≤100000

1≤p≤N1\le p \le N1≤p≤N

1≤x≤1000001\le x \le 1000001≤x≤100000

1≤L≤R≤N1\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

 

题解 

         前一段时间去学了下莫队,然后发现需要一点分块的知识,就去补了一下分块算法,发现其实就是优化的暴力。

第一道分块入门题,因为先看的电子科技大学的算法讲堂,做了一道讲解的习题,挺简单的。

其实就是把区间分成一块一块的,然后我们维护一下整块区间的最值,其他的暴力就行了,因为分成O(sqrt(n))块,每块的大小为O(sqrt(n)),所以我们可以得出时间复杂度为O(n*sqrt(n))。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#define PI atan(1.0)*4
#define e 2.718281828
#define rp(i,s,t) for (i = (s); i <= (t); i++)
#define RP(i,s,t) for (i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define push_back() pb()
#define pair<int,int> pii;
#define fastIn                    \
    ios_base::sync_with_stdio(0); \
    cin.tie(0);
using namespace std;
inline int read()
{
    int a=0,b=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
            b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        a=(a<<3)+(a<<1)+c-'0';
        c=getchar();
    }
    return a*b;
}
inline void write(int n)
{
    if(n<0)
    {
        putchar('-');
        n=-n;
    }
    if(n>=10)
        write(n/10);
    putchar(n%10+'0');
}
const int N = 1e5+7;
int block,belong[N],l[N],r[N],num,n,q;
ll Max[N],a[N];
void build(){
    int i,j;
    block=sqrt(n);
    num=n/block; if(n%block) num++;
    rp(i,1,num)
        l[i]=(i-1)*block+1,r[i]=block*i;
    r[num]=n;
    rp(i,1,n)
        belong[i]=(i-1)/block+1;
    rp(i,1,num)
        rp(j,l[i],r[i])
            Max[i]=max(Max[i],a[j]);
}
void update(int x,int val){
    a[x]+=val;
    Max[belong[x]]=max(a[x],Max[belong[x]]);
}
ll query(int x,int y){
    ll ans=0;
    int i;
    if(belong[x]==belong[y]){
        rp(i,x,y)
            ans=max(ans,a[i]);
        return ans; 
    }
    rp(i,x,r[belong[x]])
        ans=max(ans,a[i]);
    rp(i,belong[x]+1,belong[y]-1)
        ans=max(ans,Max[i]);
    rp(i,l[belong[y]],y)
        ans=max(ans,a[i]);
    return ans;
}
int main(){
	n=read(),q=read();
    build();
    while(q--){
        int opt=read(),x=read(),y=read();
        if(opt==1) update(x,y);
        else printf("%lld\n",query(x,y));
    }
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值