题目链接
卿学姐与公主
Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
某日,百无聊赖的卿学姐打开了某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]闭区间内,受伤最严重的士兵受到的伤害。
1≤N≤100000 1≤N≤100000
1≤Q≤100000 1≤Q≤100000
1≤p≤N 1≤p≤N
1≤x≤100000 1≤x≤100000
1≤L≤R≤N 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 |
Hint
注意可能会爆int哦
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=1e6+100;
int belong[MAXN],l[MAXN],r[MAXN];
int num,block;
int n;
//num为分块个数
//belong[i]表示i属于哪一块
//block表示块的大小
//l[i]表示i这块的左端点位置
//r[i]表示i这块的右端点位置
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;
}
ac代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=1e5+100;
typedef long long ll;
int belong[MAXN],l[MAXN],r[MAXN];
ll res[MAXN],a[MAXN];
int num,block;
int n;
//num为分块个数
//belong[i]表示i属于哪一块
//block表示块的大小
//l[i]表示i这块的左端点位置
//r[i]表示i这块的右端点位置
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;
}
void update(int p,ll v)
{
a[p]+=v;
res[belong[p]]=max(res[belong[p]],a[p]);
}
ll query(int ll,int rr)
{
long long ans=0;
if(belong[ll]==belong[rr])
{
for(int i=ll;i<=rr;i++) ans=max(ans,a[i]);
return ans;
}
for(int i=ll;i<=r[belong[ll]];i++) ans=max(ans,a[i]);
for(int i=l[belong[rr]];i<=rr;i++) ans=max(ans,a[i]);
for(int i=belong[ll]+1;i<=belong[rr]-1;i++) ans=max(ans,res[i]);
return ans;
}
int main()
{
int q;
scanf("%d%d",&n,&q);
memset(a,0,sizeof(a));
memset(res,0,sizeof(res));
build();
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int p;
ll v;
scanf("%d%lld",&p,&v);
update(p,v);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",query(l,r));
}
}
return 0;
}
用线段树做:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=1e5+100;
typedef long long ll;
struct node
{
int l,r;
ll mx;
}seg[MAXN*4];
void build(int i,int l,int r)
{
seg[i].l=l,seg[i].r=r,seg[i].mx=0;
if(l==r)
return;
int m=(l+r)>>1;
build(i*2,l,m);
build(i*2+1,m+1,r);
}
void update(int i,int p,ll x)
{
if(seg[i].l==seg[i].r)
{
seg[i].mx+=x;
return;
}
int m=(seg[i].l+seg[i].r)>>1;
if(p<=m) update(i*2,p,x);
else update(i*2+1,p,x);
seg[i].mx=max(seg[i*2].mx,seg[i*2+1].mx);
}
ll query(int i,int l,int r)
{
if(seg[i].l==l&&seg[i].r==r)
return seg[i].mx;
int m=(seg[i].l+seg[i].r)>>1;
if(r<=m) return query(i*2,l,r);
else if(l>m) return query(i*2+1,l,r);
else return max(query(i*2,l,m),query(i*2+1,m+1,r));
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
build(1,1,n);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int p;
ll v;
scanf("%d%lld",&p,&v);
update(1,p,v);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",query(1,l,r));
}
}
return 0;
}