1. 程式人生 > >裸裸的線段樹(hdu 1754)

裸裸的線段樹(hdu 1754)

time 一行 tro urn ria article 成績 [0 fin

線段樹的第一發。

哪天忘了還能夠讓自己找找回顧。

                                                           

線段樹操作:

build : 建樹。

update:點改動:

query:查詢 

                                                           

Input

在每一個測試的第一行,有兩個正整數 N 和 M ( 0<N<=200000,0<M<5000 ),分別代表學生的數目和操作的數目。


學生ID編號分別從1編到N。


第二行包括N個整數,代表這N個學生的初始成績,當中第i個數代表ID為i的學生的成績。
接下來有M行。每一行有一個字符 C (僅僅取‘Q‘或‘U‘) 。和兩個正整數A。B。


當C為‘Q‘的時候。表示這是一條詢問操作,它詢問ID從A到B(包含A,B)的學生其中,成績最高的是多少。


當C為‘U‘的時候,表示這是一條更新操作。要求把ID為A的學生的成績更改為B。

5 6

1 2 3 4 5

Q 1 5

U 3 6

Q 3 4

Q 4 5

U 2 9

Q 1 5

Output

對於每一次詢問操作,在一行裏面輸出最高成績。

5

6

5

9


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define INF 0x3fffffff
#define bug(a) cout<<a<<"  ----->\n"
using namespace std;

const int N=200010;

int maxt[4*N];
int a[N];
int n,q;

void build(int o,int L,int R)
{
    int m;
    if(L==R) { maxt[o]=a[L];return;}
    m=(L+R)/2;//bug(o);
    build(2*o,L,m);
    build(2*o+1,m+1,R);
    maxt[o]=max(maxt[2*o],maxt[2*o+1]);

}

int  query(int ql,int qr,int o,int L,int R)
{
    int m=(L+R)/2,ans=-INF;
    if(ql<=L&&R<=qr) return maxt[o];
    if(ql<=m) ans=max(ans,query(ql,qr,2*o,L,m));
    if(m<qr) ans=max(ans,query(ql,qr,2*o+1,m+1,R));
    return ans;
}

void update(int p,int v,int o,int L,int R)
{
    if(L==R){maxt[o]=v;return;}
    int m=(L+R)>>1;
    if(p<=m) update(p,v,2*o,L,m);
    else update(p,v,2*o+1,m+1,R);
    maxt[o]=max(maxt[2*o],maxt[2*o+1]);
}


int main()
{
    char c[2];
    int d,b;
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        //bug(1);
        build(1,1,n);

        for(int i=1;i<=q;i++)
        {
             scanf("%s%d%d",c,&d,&b);
             if(c[0]=='Q')
                 printf("%d\n",query(d,b,1,1,n));
             else
                 update(d,b,1,1,n);
        }
    }
    return 0;
}





裸裸的線段樹(hdu 1754)