http://acm.hdu.edu.cn/showproblem.php?pid=1754
RMQ问题 树状数组和线段树都行
线段树专辑的题目相当多的代码是参考别人的,又左右引用,若原作者觉得和我的代码太过相似,我感到万分抱歉,希望谅解。
#include <iostream>
#include <cstring>
using namespace std;
const int MAX = 200010;
int N,M;
struct SegTree
{
int left,right; //左右端点
int tag; //当前线段下标
int tot; //标记数
int nMax; //区间最大值
}Tree[MAX*4];
int findmax(int a,int b)
{
return a>b?a:b;
}
void clear(int k)
{
if(Tree[k].left + 1 != Tree[k].right)
{
Tree[2*k].tot = findmax(Tree[k].tot,Tree[2*k].tot);
Tree[2*k+1].tot = findmax(Tree[k].tot,Tree[2*k+1].tot);
Tree[k].nMax = findmax(Tree[k].nMax,Tree[k].tot);
Tree[k].tot = 0;
}
else
{
Tree[k].nMax = findmax(Tree[k].nMax,Tree[k].tot);
Tree[k].tot = 0;
}
return ;
}
//表示的区间为[l,r)
void buildTree(int l, int r, int k)
{
Tree[k].left = l;
Tree[k].right = r;
Tree[k].tag = k;
Tree[k].tot = 0;
Tree[k].nMax = 0;
if(l+1 == r)
return ;
//递归创建左右子树
int mid = (l+r)>>1;
buildTree(l,mid,2*k);
buildTree(mid,r,2*k+1);
}
void modify(int l, int r, int k, int value) //对区间[L,R)的修改
{
if(l==Tree[k].left && Tree[k].right==r)
{
clear(k);
Tree[k].tot = value;
clear(k);
return ;
}
int mid=(Tree[k].left+Tree[k].right)>>1;
if(l<mid)
modify(l,r,2*k,value);
if(mid<r)
modify(l,r,2*k+1,value);
if(Tree[k].left +1 == Tree[k].right)
return ;
Tree[k].nMax = findmax(Tree[2*k].nMax,Tree[2*k+1].nMax);
return ;
}
int query(int l, int r, int k)
{
if(Tree[k].left == l && Tree[k].right == r)
return Tree[k].nMax;
clear(k);
int mid = (Tree[k].left+Tree[k].right)>>1;
if(r <= mid)
return query(l,r,2*k);
else if(l >= mid)
return query(l,r,2*k+1);
else
return findmax(query(l,mid,2*k),query(mid,r,2*k+1));
}
int main()
{
while(cin>>N>>M)
{
memset(Tree,0,sizeof(Tree));
buildTree(1,N+1,1); //构造[1,N+1)线段树
for(int i=1; i<=N; i++)
{
int num;
cin>>num;
modify(i,i+1,1,num);
}
for(int i=1; i<=M; i++)
{
char ch;
int a,b;
cin>>ch>>a>>b;
if(ch == 'Q')
printf("%d\n",query(a,b+1,1));
else
modify(a,a+1,1,b);
}
}
return 0;
}