【HDU 1754】I Hate It
阿新 • • 發佈:2018-12-21
Problem Description:
很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。
這讓很多學生很反感。
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程式,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績。
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。
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
思路:這道題可以用樹狀陣列、線段樹都可以,都是單點更新,區間求最大值的過程。
其中用樹狀陣列方法時需要注意查詢的過程,要活用查詢操作。從R開始查詢,然後通過R - lowbit [ R ] 進行一個區間一個區間的查詢來減少時間複雜度,但是如果要查詢的區間的左界比L小,就只對此單點進行查詢,再進行下一個區間的查詢,直到查詢到L的位置。
下面是2種方法的程式碼。
My DaiMa(樹狀陣列):
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> using namespace std; int a[200005],build[200005],lowbit[200005],n; void GetLowbit() { for(int i = 1; i <= n ; i++) lowbit[i] = i&(-i); } ///建樹,先求出每一段的初始最大值存在build數組裡 void TreeBuild() { for(int i = 1; i <= n; i++) { build[i] = a[i]; for(int j = i-1; j > i-lowbit[i]; j--) build[i] = max(build[i],a[j]); } } ///單點更新,更新所有管轄到x的build值 void update(int x, int y) { a[x] = y; for(int i = x; i <= n; i += lowbit[i]) build[i] = max(build[i],a[x]); } ///查詢 int Find_max(int x,int y) { int maxx = a[y];///從區間右邊開始 while(y != x) { for(y -= 1; y-lowbit[y] > x; y -= lowbit[y])///根據lowbit進行一個區間一個區間的查詢 maxx = max(maxx,build[y]); maxx = max(maxx,a[y]);///當查詢的區間的左界小於x時,只對單點進行查詢 } return maxx; } int main() { int m; char ch; while(cin >> n >> m) { for(int i = 1; i <= n; i++) scanf("%d",&a[i]); GetLowbit(); TreeBuild(); int x,y; while(m--) { cin >> ch >> x >> y; if(ch == 'U') update(x,y);///單點更新 else cout << Find_max(x,y) << endl;///查詢區間最大值 } } }
My DaiMa(線段樹):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#define INF 0x3f3f3f
#define MAX 200005
using namespace std;
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
int value[MAX<<2];
void push_up(int num)
{
value[num] = max(value[num<<1],value[num<<1|1]);
}
///建樹
void TreeBuild(int l,int r,int num)
{
if(l == r)
{
scanf("%d",&value[num]);
return;
}
int mid = (l+r) >> 1;
TreeBuild(lson);
TreeBuild(rson);
push_up(num);///別忘了這一步
}
///單點更新
void update(int x,int y,int l,int r,int num)
{
if(l == x && r == x)
{
value[num] = y;
return;
}
int mid = (l+r) >> 1;
if(x <= mid) update(x,y,lson);
else update(x,y,rson);
push_up(num);///別忘了這一步
}
///區間查詢最大值
int query(int L,int R,int l,int r,int num)
{
if(L <= l && R >= r) return value[num];
int maxn = 0;
int mid = (l+r) >> 1;
if(L <= mid) maxn = max(maxn,query(L,R,lson));
if(R > mid) maxn = max(maxn,query(L,R,rson));
return maxn;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
TreeBuild(1,n,1);
char ch[3];
int x,y;
while(m--)
{
scanf("%s%d%d",ch,&x,&y);
if(ch[0] == 'U') update(x,y,1,n,1);
else printf("%d\n",query(x,y,1,n,1));
}
}
}