题目链接: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
Input Output 5 4 2 1 2 1 2 4 1 3 5 2 3 3 0 5Note
注意可能会爆int哦
Problem ID 1324 Problem Title 卿学姐与公主 Time Limit 1000 ms Memory Limit 64 MiB Output Limit 64 MiB Source 2016 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;
}