HDU 1754 I Hate It 線段樹 && Splay && zkw線段樹

Description
很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。
這讓很多學生很反感。
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績。
Input
本題目包含多組測試,請處理到文件結束。
在每個測試的第一行,有兩個正整數 N 和 M ( 0<N200000 ,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。
Output
對於每一次詢問操作,在一行裏面輸出最高成績。
Sample Input
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
Sample Output
5
6
5
9

線段樹裸題。所以就不給出裸的代碼了。
給出Splay Tree 以及 zkw線段樹 的寫法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <set>
#include <cmath>
#include <algorithm>
#include <ctime>
using namespace std;
inline bool Read ( int &x ) { char c = getchar() ; x = 0 ; bool f = 0 ; while ( !isdigit(c) ) { if ( c == '-' ) f = 1 ; if ( c == EOF ) return false ;  c = getchar() ; } while ( isdigit(c) ) { x = 10 * x + c - '0' ; c = getchar() ; } if (f) x = -x ;return true ; }
inline void Print ( int x ) { int len = 0, a[30] ; if ( x == 0 ) { putchar('0') ; return ; } if ( x < 0 ) { putchar('-') ; x = -x ; } while (x) { a[++len] = x%10 ; x /= 10 ; } while (len) putchar(a[len--]+'0') ;}
const int maxn = 200010;
static int n, m, ch[maxn][2], fa[maxn], val[maxn], cnt, root=1, maxx[maxn], a[maxn] ;
#define L ch][0
#define R ch][1

inline void new_node ( int rt ) {
    rt[val] = a[rt-1] ;
    rt[L] = rt[R] = rt[fa] = 0 ;    
}

inline void push_up ( int x ) { x[maxx] = max ( max ( x[R][maxx], x[L][maxx] ), x[val] ) ; }
inline int create_tree ( int l, int r ) {
    if ( l > r ) return 0 ;
    register int rt = l+r >> 1 ;
    new_node(rt) ; 
    val[rt] = a[rt-1] ; 
    (rt[L] = create_tree ( l, rt-1 )) [fa] = rt ;
    (rt[R] = create_tree ( rt+1, r )) [fa] = rt ;
    push_up(rt) ;
    return rt ;
}

inline void Rotate ( int x ) {
    register int y = x[fa], z = y[fa], T = y[R]==x, son = ch[x][T^1] ;
    if ( y == root ) root = x ;
    if ( y != root ) ch[z][ z[R]==y ] = x ;
    fa[x] = z ;
    fa[y] = x ;
    if ( son ) fa[son] = y ;
    ch[y][T] = son ;
    ch[x][T^1] = y ;
    push_up(y) ;
}

inline void splay ( int x, int tar = 0 ) {
    while ( x!=root && fa[x]!=tar ) {
        register int y = x[fa], z = y[fa] ;
        bool f1 = y[R]==x, f2 = z[R] == y ;
        if ( y == root || z == tar ) ;
        else if ( f1^f2 ) Rotate(x) ;
        else Rotate(y) ;
        Rotate(x) ;
    }
    push_up(x) ;
}

char cmd[5] ;
inline void update ( int x ) {
    push_up(x) ;
    if ( x != root ) update ( x[fa] ) ;
}
int main() {
    register int i, j, k, x, y ;
    while ( Read(n) ) {
        Read(m) ;
        cnt = 0;
        a[n+1] = a[n+2] = a[n+3] = a[n+4] = a[0] = -1000000000 ;
        for ( i = 1 ; i <= n ; i ++ ) 
            Read(a[i]) ;
        root = n+4>>1;
        create_tree(1,n+3) ;
        for ( i = n+3 ; i ; i -- ) 
            push_up(i) ;
        while (m--) {
            scanf ( "%s", cmd ) ;
            if ( cmd[0] == 'Q' ) {
                Read(x) ; Read(y) ;
                splay(x) ;
                splay(y+2,x) ;
                printf ( "%d\n", root[R][L][maxx] ) ;
            } else {
                Read(x) ; Read(k) ;
                ++ x ;
                x[val] = k ;
                splay(x) ;
                update(x) ;
            }
        }
    }
    return 0 ;
}

zkw線段樹:

#include <bits/stdc++.h>
using namespace std ;
inline bool Read ( int &x ) {
    char c = getchar() ; bool f = 0 ; x = 0 ;
    while ( !isdigit(c) ) {
        if ( c == '-' ) f = 1 ;
        if ( c == EOF ) return false ;
        c = getchar() ;
    }
    while ( isdigit(c) ) {
        x = 10 * x + c - '0' ;
        c = getchar() ;
    } if (f) x = -x ;
    return true ;
}
const int maxn = 200010 ;
int n, m, tree[maxn*3], Base ;
int Max ( int x, int y ) { return x > y ? x : y ; }
void push_up ( int h ) { tree[h] = Max ( tree[h<<1], tree[h<<1|1] ) ; }
void create_tree() {
    for ( Base = 1 ; Base <= n ; Base <<= 1 ) ;
    for ( register int i = 1 ; i <= n ; i ++ ) 
        Read(tree[Base+i]) ;
    for ( register int i = Base-1 ; i>0 ; i -- ) 
        push_up(i) ;
}
int query ( int s, int t ) {
    int rec = -1 ;
    for ( s = s+Base-1, t = t+Base+1 ; s^t^1 ; s >>= 1, t >>= 1 ) {
        if ( ~s&1 ) rec = Max ( rec, tree[s^1] ) ;
        if ( t&1 ) rec = Max ( rec, tree[t^1] ) ;
    }
    return rec ;
}
void update ( int s, int val ) { for ( tree[s+=Base] = val, s>>=1 ; s ; s >>= 1 ) push_up(s) ; }
char cmd[5] ;
int main() {
    register int x, y ;
    Read(n) ; Read(m) ;
    create_tree() ;
    while (m--) {
        scanf ( "%s", cmd ) ;
        Read(x) ; Read(y) ;
        if ( cmd[0] == 'Q' ) printf ( "%d\n", query(x,y) ) ;
        else update ( x, y ) ;
    }
    return 0 ;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章