http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1752
这是题目链接,挺好的一道练习线段树的模板题,单点修改加上求区间最大值及其下标,其实这题在你理解了线段树后真的是非常简单(勿喷啊,我真的是菜,理解了好久终于懂了有点兴奋庆祝一下自己的学习成果),思路没啥说的大家估计都知道,就是讲解一下代码的含义吧,有助于像我一样的弱鸡理解线段树(大佬勿喷)。
#include <bits/stdc++.h>
typedef long long ll;
#define pb push_back
#define db double
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
using namespace std;
const int N = 111111;
int tree[N << 2];//保留的是最大值
int posn[N << 2];//保留下标
int pos;//保留最大值的下标
void pushup(int rt)
{
if(tree[rt << 1] > tree[rt << 1|1])//求最大值,更新区间最大值
{
tree[rt] = tree[rt << 1];
posn[rt] = posn[rt << 1];//下标随之更新
}
else
{
tree[rt] = tree[rt << 1 | 1];
posn[rt] = posn[rt << 1 | 1];
}
}
void build(int l,int r,int rt)
{
if(l == r)
{
scanf("%d",&tree[rt]);
posn[rt] = l;
}
else
{
int m = (l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
}
void update(int p,int c,int l,int r,int rt)
{
if(l == r)
{
tree[rt] = c;
}
else
{
int m = (l+r)>>1;
if(p <= m)
{
update(p,c,lson);
}
else
{
update(p,c,rson);
}
pushup(rt);
}
}
int query(int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R)
{
pos = posn[rt];
return tree[rt];
}
else
{
int m = (l + r) >> 1;
int ret1 = INT_MIN;
int ret2 = INT_MIN;
if(L <= m)
{
ret1 = query(L,R,lson);
}
if(R > m)
{
ret2 = query(L,R,rson);
}
if(ret1 > ret2)
{
pos = posn[rt*2];
}
else//包含了等于时右儿子的下标一定比左二子大所以为了满足题意。
{
pos = posn[rt*2|1];
ret1 = ret2;
}
return ret1;
}
}
int main()
{
int n,m;
while(~scanf("%d",&n))
{
build(1,n,1);
scanf("%d",&m);
char op[2];
int a,b;
while(m--)
{
scanf("%s",op);//这里就是如果输入单个字符就会出现一些输入的问题,为了避免就直接来个长度为二的字符串。
if(op[0] == 'Q')
{
printf("%d %d\n",pos,query(1,n,1,n,1));
}
else
{
scanf("%d%d",&a,&b);
update(a,b,1,n,1);
}
}
printf("\n");
}
}