题目传送门
题意:给定一个原始数组,有2种操作,第一种操作是单点修改ID为A的学生的成绩改为B,第二种操作是询问区间A到B中分值最大的一位。
思路
用线段树维护区间最大值,每次修改之后不断向上更新区间最大值即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
const int mod=1e9+7;
const int INF=0x7fffffff;
const ll LLINF=0x7fffffffffffffff;
const double EPS=1e-10;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define debug cout<<"debug"<<endl;
//#define int long long
int a[N];
struct tree
{
int l,r,pre,add;
}t[N<<2];
void build(int p,int x,int y)
{
t[p].l=x;t[p].r=y;
if(x==y)
{
t[p].pre=a[x];
return ;
}
int mid=x+y>>1;
build(p<<1,x,mid);
build(p<<1|1,mid+1,y);
t[p].pre=max(t[p<<1].pre,t[p<<1|1].pre);
}
void change(int p,int x,int y,int z)
{
if(x<=t[p].l&&t[p].r<=y)
{
t[p].pre=z;
return ;
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid)
change(p<<1,x,y,z);
if(y>mid)
change(p<<1|1,x,y,z);
t[p].pre=max(t[p<<1].pre,t[p<<1|1].pre);
}
int ask(int p,int x,int y)
{
int ans=0;
if(x<=t[p].l&&t[p].r<=y)
{
ans=max(ans,t[p].pre);
return ans;
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid)
ans=max(ans,ask(p<<1,x,y));
if(y>mid)
ans=max(ans,ask(p<<1|1,x,y));
return ans;
}
signed main()
{
IOS;
//freopen("","r",stdin);
//freopen("","w",stdout);
int n,m;
while(~scanf("%d%d",&n,&m))
{
memset(t,0,sizeof t);
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
}
build(1,1,n);
while(m--)
{
char ch;
int x,y;
scanf(" %c %d %d",&ch,&x,&y);
if(ch=='U')
{
change(1,x,x,y);
}
if(ch=='Q')
{
cout<<ask(1,x,y)<<endl;
}
}
}
}