HDU:1754 I Hate It

来源:互联网 发布:linux关机时执行脚本 编辑:程序博客网 时间:2024/05/19 01:10

开始刷线段树的题。上一道是单值加减,区间求和,我用树状数组过掉了。这道题是单值更新,区间求最值,只能用线段树了。

用了watashi翻译的那本书上的模版,把半闭半开的区间改成了全闭区间。另外数组开的大小问题还是不太懂。。

 

#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <cmath>#include <queue>#include <vector>#include <map>#include <stack>#include <algorithm>#define MAXN 200005#define MOD 1000000007#define INF -2139062144#define ll long long//ios::sync_with_stdio(false)using namespace std;int N,M,mxn;const int MAX_N = 1 << 18;int dat[2*MAX_N-1];void Init(){    mxn=1;    while(mxn<N) mxn*=2;    memset(dat,0,sizeof(dat));}void update(int val,int k){    k+=mxn-1;//得到在线段树上的编号    dat[k]=max(val,dat[k]);//更改当前结点的值    while(k/2>0)//向上更新,父亲存在的时候    {        k=k/2;//父亲结点        dat[k]=max(dat[2*k],dat[2*k+1]);//父亲结点为左右孩子的较大值    }}int Query(int a,int b,int k,int l,int r)//闭区间{    if(r<a||b<l) return 0;    if(a<=l&&r<=b) return dat[k];    else    {        int v1=Query(a,b,k*2,l,(l+r)/2);        int v2=Query(a,b,k*2+1,(l+r)/2+1,r);        return max(v1,v2);    }}int main(){    while(scanf("%d%d",&N,&M)!=EOF)    {        Init();        for(int i=1; i<=N; ++i)        {            int t;            scanf("%d",&t);            update(t,i);        }        while(M--)        {            char str[5];            int a,b;            scanf("%s%d%d",str,&a,&b);            if(str[0]=='Q')            printf("%d\n",Query(a,b,1,1,mxn));            else update(b,a);        }    }    return 0;}


 

0 0