---恢復內容開始---
今天50分,我自閉
眼瞎看錯了一道題,然后兩道題的代碼都出了點小毛病,自閉
真的競賽我要這樣可以收拾收拾退役了真的,眼睛不能這么瞎了考試莫得人幫忙改了
如果一切都沒問題今天應該有130,啊!!!!!!!!!!!!!!!!!
今天兩題可以用堆,一題模擬隨便寫寫就過了,(所以我為什么考這么差)
進入正題
題目一覽(其實就3道題)(CZR到底是誰這么愛數學和折磨我們)
- 24點
- 小游戲
- 中位數
題1. 24點
題目描述
1.1 Background
CZR很喜歡學數學,但是他數學一直不好,所以他決定玩24點來練習自己.
1.2 Description
然而由於他數學不好,所以他只會加減法:給定四個數,請問是否能通過加法和減法來得到24點.為了訓練自己,他每次都會進行5個24點游戲.
1.3 Task
1.3.1 Input
輸入有5行,其中每一行為一個24點游戲,為進行24點的4個數字.
1.3.2 Output
輸出有5行,其中每一行的游戲中如果能得到24點,則輸出’Yes.’;否則輸出’No.’.
樣例數據
1.4 Sample
1.4.1 Input
1 2 3 4
6 6 6 6
5 6 7 8
5 6 7 6
10 10 5 1
1.4.2 Output
No.
Yes.
No.
Yes.
Yes.
數據范圍
對100%的數據,游戲的所有數字≤ 100
題目分析
看到這個“所有數字≤ 100 ”了嗎!開不開心!快不快落!隨便寫個深搜,寫個暴力,甚至打個表,就過了啊!!!!!不會超時不會超內存,當真是個水題
(然鵝我把一個減號打成了加號WA了5個點自閉)
說說我的思路啊, 輸入有5行,那么在一個for循環里面寫;對於輸入的4個數,我們開一個數組,記錄每一個數的所有情況(二維,挺小的,【5】【31】就行,反正只有加減隨便寫),然后4個for循環模擬累加,最后在到達第4個點的時候掃一遍看有沒有==24的,有就輸出“Yes.”沒有就輸出“No.”(看清楚這里,首字母大寫,有個句號)
是真的沒啥好講的,簡簡單單,我來記一下其他人的思路(應該可以的吧...)
最引人注目的tcr大佬,
妙啊!!!!!!!!!簡潔明了還不容易錯,tqltql
kqy和jyy似乎都是深搜,這種很正常的思路也就不說了大家差不多(耗時間和耗空間的不太一樣大體思路差別不大我覺得)
好的上代碼
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int t1=1; int add[5][31],jian[5][31]; void ss(int t,int k) { for (int i=1; i<=t1; i++) add[t][i]=add[t-1][i]+k; for (int i=t1+1; i<=t1*2; i++) add[t][i]=jian[t-1][i-t1]+k; for (int i=1; i<=t1; i++) jian[t][i]=jian[t-1][i]-k; for (int i=t1+1; i<=t1*2; i++) jian[t][i]=add[t-1][i-t1]-k; if (t==4) { int flag=0; for (int i=1; i<=t1*2; i++) if (add[t][i]==24||jian[t][i]==24) { cout<<"Yes."; flag=1; break; } if (flag==0) cout<<"No."; } t1*=2; } int main() { //freopen("24.in","r",stdin); //freopen("24.out","w",stdout); int a[5]; for (int ii=1; ii<=5; ii++) { t1=1; memset(add,0,sizeof(add)); memset(jian,0,sizeof(jian)); cin>>a[1]>>a[2]>>a[3]>>a[4]; add[1][1]=a[1]; jian[1][1]=-a[1]; for (int i=2; i<=4; i++) ss(i,a[i]); cout<<endl; } //fclose(stdin); //fclose(stdout); return 0; }
題2.小游戲
題目描述
2.1 Background
CZR雖然已經是個大學生了,但是他還是喜歡在家里偷偷玩跳格子.
2.2 Description
CZR的家里有連續的N + 1塊地磚,編號為0到N,他在每一塊地磚上
都寫上了一個數字.
一開始他在0號地磚,這塊地磚的分數為0,每次他都會后面跳一步
但是他不一定需要跳到最后.
因為他跳遠能力不行,所以他一步只能往后跳L到R個格子,也就是說
在地磚i時,他只能跳到地磚i + L到i + R中的一塊地磚.
他進行一次游戲的分數總和是他跳到的所有地磚的分數之和.
他現在想獲得最大的分數,來證明自己的數學能力很強,所以他需要
知道最大分數是多少.
2.3 Task
2.3.1 Input
輸入的第一行為一個數N,表示地磚個數.
第二行有兩個數L和R,表示他一次跳遠能跳的范圍.
第三行有N個正整數,分別表示1號地磚到N號地磚上的分數.
2.3.2 Output
輸出只有一行,為能跳出的最大分數.
樣例數據
2.4 Sample
2.4.1 Input
5
1 2
1 2 3 4 5
2.4.2 Output
15
數據范圍
2.6 Constraint
對50%的數據,N ≤ 1000.
對於100%的數據,N ≤ 5 ∗ 105.
可能存在負數
題目分析
啊稍微難了一點呢,不過也還行,看起來像不像動規?
不要退縮,這題難的並不是動規
我們很容易就能發現(發現不了拿着草稿紙推一遍樣例絕對能發現):
令F[i]表示CZR跳到第i個格子上時能夠獲得的最大分數
那么,F[i]=max{F[i-l],...F[i-r}+a[i]; //注意!題目上說的是可以跳到第 i + l 到 第 i + r !不是第 i + l 或 第 i + r,就這個把我坑慘了這題一分沒有
題面上說,“對50%的數據,N ≤ 1000.”,它肯定不是胡編的數字,我們如果求上面這個式子,那么它的時間復雜度為O(N^2),也就是說只能過百分之50的點(之后的就TLE啦)
那么正解是什么呢?(別想了這個式子肯定還是要有的必須推出來而且必!須!推!對!)
我們再重新看一下這個問題,由於這個 i 要取遍1-n,所以我們可以簡化為要求一個長度固定的區間的最大值
於是老師給出了如下幾種優化方式(是的優化一下就可以了)
- 單調隊列 時間復雜度O( n ) <------正解
- ST表 時間復雜度O(n log n + n )
- 堆 時間復雜度O(n log n)
先說 單調隊列:
固定區間的最大值,單調隊列很好寫也很好想,只要分為進隊和出隊兩個步驟,掃過去就好了(然鵝老師的代碼我沒看懂,要再多琢磨琢磨,其實我覺得堆要好懂一點(小聲))
再說 ST表
(直接引用過來了(我太懶了),ST表我當時沒怎么聽懂,也是要再琢磨的)
最后說 堆:(萬眾矚目(不是))
至於堆的基本操作,我是會了的,STL也可以用(不過有一、、麻煩),洛谷模板題可以看一看(堆學一學還是蠻好的)https://www.luogu.org/problem/P3378
題3.中位數
題面描述
3.1 Background
雖然CZR數學很爛,但是他還是想證明一下自己的數學能力,今天他
想要表演一下瞬間計算中位數.
3.2 Description
一開始集合為空,每次有兩個操作:
1 x:告訴CZR當前集合中再加入一個數x.
2 :詢問CZR當前集合的中位數是多少.
3.3 Task
3.3.1 Input
輸入的第一行為一個數N,表示操作數量.
接下來的N行,每行有一個操作,如題目所示.
3.3.2 Output
對於每一個詢問操作,請輸出當前的中位數.
請一行輸出一個答案.
對於小數請只輸出十分位.
樣例數據
3.4 Sample
3.4.1 Input
7
1 1
2
6
1 2
1 3
2
1 4
2
3.4.2 Output
1 2
2.5
數據范圍
3.6 Constraint
對於30%的數據,N ≤ 1000.
對於100%的數據,N ≤ 5 ∗ 105.正整數,在 int 范圍內
題目分析
看到那個30%的數據了嗎,就是留來我們騙分的,sort會不會打,一遍就過,30分到手(注意輸出小數的時候,".0"是作為整數的小數點后不要)
那么正解是什么呢,還是堆
我們維護兩個堆,一個大根堆和一個小根堆
大根堆存儲小的數據,小根堆存儲大的數據
我們看一下下面這個圖
我們每次保證插入的元素使小根堆和大根堆的大小不超過1,並且滿足堆的性質,那么我們的答案中位數就一定是在某一個堆堆頂或是兩個堆的堆頂平均值
剩下的一些基本操作就不說了,同上題(我也不明白為什么我們並沒有上堆而考了堆)
代碼依舊——
沒有,改天我自己寫,老師的代碼用的STL我並不是太懂
總而言之,這篇題解可能還需要日后的修正(耗時1-2小時)
但是現在,OVER!
完結撒花!(看不懂來找我)(其實你更應該找老師)
感謝觀看 ありがとうございます