1. 程式人生 > >題解 P1531 【I Hate It】

題解 P1531 【I Hate It】

這道題明明是裸的線段樹,蒟蒻卻80分了五六次。。。


------------

根據題意,顯然是維護一棵單點修改區間查詢的線段樹,於是直接套區間修改的程式碼。。。

結構體,即為樹上的節點。

1 struct node{
2     int l, r;
3     int val;
4 } tree[maxn * 4];


建樹,注意:將讀入放到這裡來!!原本是在main裡面讀入然後儲存到stu陣列中,結果就一直80分!!

 1 void Build(int l, int r, int pos) { //
 2     tree[pos].l = l;
 3     tree[pos].r = r;
4 if(l == r) { 5 int a; 6 a = read(); 7 tree[pos].val = a; 8 } 9 else { 10 int mid = (l + r) >> 1; 11 Build(l, mid, pos * 2); 12 Build(mid + 1, r, pos * 2 + 1); 13 tree[pos].val = max(tree[pos * 2].val, tree[pos * 2 + 1].val);
14 } 15 }


區間修改函式:
1. 如果直接是要求的區間,直接修改即可。
2. 反之則分配到左右子樹上面去。
3. 回溯。

 1 void Update(int l, int r, int d, int pos) {
 2     if(tree[pos].l == l && tree[pos].r == r) {
 3         tree[pos].val = max(d, tree[pos].val);
 4         return ;
 5     }
 6     int mid = (tree[pos].l + tree[pos].r) >> 1
; 7 if(r <= mid) Update(l, r, d, pos * 2); 8 else if(l > mid) Update(l, r, d, pos * 2 + 1); 9 else { 10 Update(l, mid, d, pos * 2); 11 Update(mid + 1, r, d, pos * 2 + 1); 12 } 13 tree[pos].val = max(tree[pos * 2].val, tree[pos * 2 + 1].val); 14 }


區間查詢函式:

其實流程和修改挺像的。

 1 int Query(int l, int r, int pos) {
 2     if(tree[pos].l == l && tree[pos].r == r) {
 3         return tree[pos].val;
 4     }
 5     int mid = (tree[pos].l + tree[pos].r) >> 1;
 6     if(r <= mid) return Query(l, r, pos * 2); 
 7     else if(l > mid) return Query(l, r, pos * 2 + 1); 
 8     else {
 9         return max(Query(l, mid, pos * 2), Query(mid + 1, r, pos * 2 + 1));
10     }
11 }


主要處理部分:

read()是快速讀入函式,然後要注意因為本題是單點修改,所以Update函式的l,r兩個引數其實是一樣的。

1 scanf("%s", &op);
2         l = read(); r = read();
3         if(op == 'Q') printf("%d\n", Query(l, r, 1));
4         else Update(l, l, r, 1);

emmm....大概就這麼多了。

程式碼64ms,氧化後36ms。