最高分是多少
阿新 • • 發佈:2017-11-03
int swap sub 樹狀 div 某某 編號 describe 大小
先來說說這題的3種做法: 最簡單的就是暴力了。每次查詢直接做。 修改復雜度O(1),查詢復雜度O(N)
……如果他們手一抖,寫成N<=100000,M<=100000怎麽辦?
!!!註意:以下內容涉及高級數據結構!!!
首先,有ACM經驗的選手,一看這個題,第一反應,線段樹好~
線段樹這種數據結構,修改O(logn),查詢O(logn),但是要預處理O(nlogn)
這個,如果沒有ACM經驗,也不打算認真做ACM的同學,看看就好。
有沒有什麽辦法,普通人能去想出來,又不需要專門去學過高級數據結構呢?
有一個,叫塊狀鏈表(其實塊狀數組也行吧)。
好吧,其實分塊的思想也不怎麽常見,談針對面試的算法的思路,都談分治、貪心、遞推、動態規劃,沒見人說過分塊的樣子。但是,分塊是比較容易理解的。
很簡單,現在我們把整個N大小的數組按順序拆成sqrt(n)(根號n)個小數組,每個小數組有sqrt(n)個元素
比如 1 2 3 4 5 6 7 8 9
現在拆成
1 2 3
4 5 6
7 8 9
然後對每一個小塊,我們除了改掉相應位置的值,還要額外記錄一下整個小塊的最大值。
如果我更新的時候,那個小塊的最大值增大,那很簡單,最大值也增大了。
如果把最大值改小了呢?為了正確性,只能把整個小塊掃一遍,重新算出最大值了。
所以,修改的復雜度是O(sqrt(n))
現在看查詢。我們要充分利用分小塊以後的信息。
比如要查詢2到9的最大值。按之前最樸素的暴力的做法,我要訪問2、3、4、5、6、7、8、9
現在有小塊的最大值信息了,我只要判斷每個小塊是否在查詢區間內,不在的沒用,一部分在的,就暴力查找,如果是完整在查詢區間內的,我們就利用之前算好的這個小塊內的最大值。
所以,分塊的情況下,查詢2到9的最大值,需要看看2、3,以及4~6的最大值,7~9的最大值。
很容易證明,查詢的復雜度是O(sqrt(n))的(最壞是sqrt(n)個塊全部要用,左右2邊只蓋住sqrt(n)-1個數,要暴力遍歷過去)
//TODO:在這裏補上分塊法的代碼
3種流派全部可過,但是明顯的,在極限數據情況下,能夠輕易區分出普通應聘者,會動腦的應聘者和有ACM經驗的應聘者了。
最高分是多少
題目描述
老師想知道從某某同學當中,分數最高的是多少,現在請你編程模擬老師的詢問。當然,老師有時候需要更新某位同學的成績.輸入描述:
輸入包括多組測試數據。 每組輸入第一行是兩個正整數N和M(0 < N <= 30000,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。
輸出描述:
對於每一次詢問操作,在一行裏面輸出最高成績.示例1
輸入
5 7 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 4 5 U 2 9 Q 1 5
輸出
5 6 5 9
分析:
這個題目樹狀數組線段樹都是OK的,但是沒有涉及到對區間的操作,樹狀數組在時間和空間上面的代價都要小很多。
牛客網題解:
暴力,線段樹,塊狀鏈表
鏈接:https://www.nowcoder.com/questionTerminal/3897c2bcc87943ed98d8e0b9e18c4666
來源:牛客網
先來說說這題的3種做法: 最簡單的就是暴力了。每次查詢直接做。 修改復雜度O(1),查詢復雜度O(N)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <stdio.h>
#include <algorithm>
using namespace std;
const int MAXN=100000;
int data[MAXN+5];
int querymax ( int l , int r ) {
int ans=data[l];
for ( int i=l+1;i<=r;i++) ans=max(ans,data[i]);
return ans;
}
void update( int idx, int value){
data[idx]=value;
}
int main(){
int n,m;
while (~ scanf ( "%d%d" ,&n,&m)){
for ( int i=1;i<=n;i++){
scanf ( "%d" ,&data[i]);
}
char order;
int a,b;
for (;m--;){
scanf ( " %c%d%d" ,&order,&a,&b);
if (order== ‘U‘ ){
update(a,b);
} else if (order== ‘Q‘ ){
if (a>b)swap(a,b);
printf ( "%d\n" ,querymax(a,b));
}
}
}
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
#include <stdio.h>
#include <algorithm>
using namespace std;
const int MAXN=100000;
int data[MAXN+5];
int maxarr[MAXN*4+5];
void build( int p, int l, int r) {
if (l==r){
maxarr[p]=data[l];
return ;
}
int m = ( l + r ) >> 1 ;
int lchild=p<<1,rchild=p<<1|1;
build ( lchild , l , m ) ;
build ( rchild , m+1 , r ) ;
maxarr[p]=max(maxarr[lchild],maxarr[rchild]);
}
int querymax ( int L , int R , int p , int l , int r ) {
if ( L <= l && r <= R ) {
return maxarr[p];
}
int m = ( l + r ) >> 1 ;
int lans=-1,rans=-1;
if ( L <= m ) lans=querymax ( L , R , p << 1 , l , m ) ;
if ( m < R ) rans=querymax ( L , R , p << 1 | 1 , m + 1 , r ) ;
if (lans==-1) return rans;
if (rans==-1) return lans;
return max(lans,rans);
}
void update( int idx, int value, int p, int l, int r){
if (l==r&&l==idx){
maxarr[p]=value;
return ;
}
int m = ( l + r ) >> 1 ;
if ( idx <= m ) update( idx, value, p << 1, l, m );
if ( m < idx ) update( idx, value, p << 1|1, m+1, r );
maxarr[p]=max(maxarr[p<<1],maxarr[p<<1|1]);
}
int main(){
int n,m;
while (~ scanf ( "%d%d" ,&n,&m)){
for ( int i=1;i<=n;i++){
scanf ( "%d" ,&data[i]);
}
build(1,1,n);
char order;
int a,b;
for (;m--;){
scanf ( " %c%d%d" ,&order,&a,&b);
if (order== ‘U‘ ){
update(a,b,1,1,n);
} else if (order== ‘Q‘ ){
if (a>b)swap(a,b);
printf ( "%d\n" ,querymax(a,b,1,1,n));
}
}
}
return 0;
}
|
3種流派全部可過,但是明顯的,在極限數據情況下,能夠輕易區分出普通應聘者,會動腦的應聘者和有ACM經驗的應聘者了。
最高分是多少