Time of Update: 2018-12-04
這算是很經典的多模式串多原串的題目了,匹配的複雜度是O(n)的,這樣,直接上自動機,注意判重另外開一個vis變數表示第turn躺是否訪問過此結點即可。運用靜態分配記憶體,跑了156ms。 My Code:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>using namespace std;const int MAX=101100;const int
Time of Update: 2018-12-04
這題暴力複雜度是O(2^n)的,對於24的複雜度明顯不可做,我的方法是進行最佳化,枚舉前n/2個,得到每個陷阱對應的寶物編號,這樣對應了一個映射,然後枚舉剩下的寶物,找到對應陷阱所對應的前半部分寶物,所有寶物的價值之和就是目前的答案,取最大的即可。 寶物和陷阱可以用int和long long壓縮,最後放入map中。複雜度O(2^(n/2)) My Code:#include <cstring>#include <cstdio>#include
Time of Update: 2018-12-04
在很多情況下,我們可以用一個整數或者多個整數把多變的狀態壓縮,這樣有利於空間上的最佳化,雖然在代碼量上並不能得到多少的好處,但是遇到資料量大的時候還是可以有一定的效果的。以POJ1753為例,這題是推薦題中的簡單題了,一般的搜尋完全可以過,甚至不用搜尋。。。我的方法是把BFS的狀態壓縮,由於每個牌面就4乘以4,也就是16個格子,每個格子只有黑白兩種狀態,用一個int型數就可以裝下整個狀態。將牌面從上到下從左至右編號0到15,這樣int型數從低位開始的第i位標記為0或者1,分別表示白色和黑色,用位
Time of Update: 2018-12-04
第一次寫EK,寫了一個晚上沒有什麼大的進展,仔仔細細研究了一下論文,自己想了BFS找增廣路的過程,寫了一個鄰接矩陣版的EK交上去,居然只跑了30多毫秒,不知道什麼情況。。。。My Code:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>using namespace std;const int oo=0x3
Time of Update: 2018-12-04
因為今天要打地區賽的緣故,昨晚CF沒有做,現在放出ABC的思路,後兩題表示不怎麼會,一題圖論,一題數論,平時都是隊友搞定的。。。 A Next Test這題很簡單,寫的暴力點也無妨,n<=50的,開個3200大小的數組,然後記錄use[i]表示i這個序號是否被用過,然後從頭到尾迴圈一遍即可,時間複雜度是O(n)的。 My Code:#include <iostream>#include <cstdio>#include
Time of Update: 2018-12-04
經過去除code變數加上手寫隊列,把代碼的時間最佳化了不少,但是看了一下status,感覺壓力很大,一幫的0ms。。。。 code是沒用的記錄,可以刪除,成型代碼如下: #include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>using namespace std;const int MAX=500000;struct Node{int table;int
Time of Update: 2018-12-04
做過TC的比賽感覺上了相對來說,CodeForces的比賽應該會簡單一些,不過很可惜,那晚第三題並沒有拍出來,可能是時間不夠了,卡在第一題上太久,有點悲劇。。。。 A.Rind
Time of Update: 2018-12-04
本題是典型的最大流最小割模型,利用最大流等於最小割求解,將每個城市拆成兩個點,之間連容量為w的邊,注意起點和終點連容量為無窮大的邊,然後為了方便,起點連源,終點連匯,容量也為無窮大,城市之間連容量為無窮大的雙向邊,直接跑最大流即可。 My Code:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>using namespace std;int
Time of Update: 2018-12-04
這道題的題意就是如果遇到相同的號碼就輸出,這樣用STL中的map加上string可以寫的很簡單,但是結果就不是很好了。好囧的時間,2000ms的題1954ms卡過,在代碼中的map可以用離散化hash代替,可以大大地最佳化代碼。 My Code思路就是讀取字串,hash,然後對應的映射加1,最後統計大於等於2的全部輸出即可,cnt計數器,當cnt等於0的時候輸出No duplicates.之前漏了這個,WA了兩次。。。 #include <iostream>#include <
Time of Update: 2018-12-04
這題算是資料結構類型的題目了吧,運用並查集可以快速地解決此類問題,從頭往後讀取資料,如果讀取到的兩個點不在同一個集合裡,就將他們合并,否則,這條邊就是多餘的,將多餘的邊放入棧st中。處理完邊之後,線性掃一遍結點數組,找出所有的根結點放入棧done中。 之後從st中取出一元素,將done中的兩個元素連起來,然後任意去掉一個元素,留下一個元素,不斷進行,直到棧st空了為止結束迴圈。 這個過程主要是運用好棧和並查集。。第一題和第二題比較簡單,就不在此多說,剩下的題目嘗試寫了下,沒有寫出。 My
Time of Update: 2018-12-04
好久沒寫掃描線了,今天想拿些資料結構題目練手,在題目分類裡面看到了這題,就拍上了。掃描線排序離散化,線段樹的區間代表y的腳標,然後對y進行離散化,二分尋找對應的y。val用來記錄區間被覆蓋的次數,嚴格O(nlogn)的訪問,然後直接掃描一遍就可以了。對精度要求不高,原來數組開小了,eps設成1e-8就WA了,不知道是資料開到1000不夠還是eps太小。 My Code: #include <iostream>#include <cstdio>#include
Time of Update: 2018-12-04
這道題本來是用dp做的,這幾天都在練dp,看了一下,可以用線段樹來做,就嘗試了一下,雖然不好寫,但是還是可以做的- -。這題的關鍵在於預先處理出每個方格可以向左向右分別擴充多少長度,記錄l[i]和r[i]分別表示第i個格子可以向左向右擴充的格子數,那麼如果選中了第i個格子,面積就是(l[i]+r[i]+1)*h[i],這樣最後線性掃一遍就可以了。l[i]的求法,最直接的方法就是枚舉,從該格子向左枚舉,找到第一個比它小的格子,這個格子右邊的都是可擴充的。這樣做複雜度是O(n^2)的,對於10000
Time of Update: 2018-12-04
無意中看到這題,就切了一下,感覺這題很適合剛剛接觸散列表和字串處理的朋友,直接對字串hash就可以了,用map暴力不知道能不能過,沒有嘗試過。 My Code:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>using namespace std;const int MAX=210000;const int mod=100007;struct
Time of Update: 2018-12-04
找一個最長字串區間,滿足裡面每個字母出現的次數為偶數巧妙的利用了位元運算的性質將所有的狀態存在一個整數裡,位元的每位是0 1 分別表示字母出現的偶 奇次,在利用首碼和#include <cstdio>#include <string.h>#include <algorithm>using std::sort;const int maxn=10005;char str[105];int cnt[maxn];int pin[maxn];int
Time of Update: 2018-12-04
這題一眼看去就是更新區間尋找點,典型的樹狀數組解法,但是如果用三維樹狀數組的話,會遇到一個難題,那就是怎麼分割?我們看簡單的問題開始,對於一維的情況,將區間(a,b)進行更新,那麼就在a處加v,b+1處減v即可。對於二維的情況,那就麻煩一點,將地區(x1,y1)到(x2,y2)進行更新,那麼就在(x1,y1)處加v,在(x2+1,y1)和(x1,y2+1)處減v,在(x2+1,y2+1)處加v即可。那麼三維的呢?經過畫圖,我得到了結論,那就是(x1,y1,z1)加v,和(x1,y1,z1)相鄰奇
Time of Update: 2018-12-04
常見的多限制匹配問題,每頭牛需要選擇一種食物和一種飲料,每種食物和飲料只能被一頭牛選到,所以直接建圖,分三部分,左邊為所有的食物,和源連邊,容量為1,右邊是飲料,和匯連邊,容量為1,為了達到每頭牛都只能選擇一種食物和飲料的目的,中間為牛,每頭牛拆成兩個點,兩個點連邊,容量為1,點1和食物連,點2和飲料連,在這基礎上直接跑最大流即可。 My Code:#include <cstdio>#include <cstdlib>#include
Time of Update: 2018-12-04
這道題裸的dp方程應該可以寫的出來,我記錄的狀態如下:dp[i][j]表示以a[i]為第一個元素,a[j]為第二個元素的斐波那契序列的最大長度,這樣i<=j轉移方程:dp[i][j]=dp[j][k]+1,其中a[k]=a[i]+a[j]從後向前掃描,每次更新dp值後更新最大長度以及第一第二項,最後的答案直接根據第一第二項迭代即可現在遇到的最大問題就是轉移,裸的轉移是O(n)的,直接從前向後掃一遍,找到第一個合格k,這樣總的複雜度是枚舉加上掃描,是O(n^3)的,明顯對n為3000的資料來
Time of Update: 2018-12-04
這題囧了,看完了題目和範例,非常興奮的寫了個0-1背包上去,發現WA了,後來仔細想想不對,要求的是最大的安全係數(暫且這麼認為 - -),這樣定義的方程最有比較大的變化。做如下定義://定義dp[i]為搶了i元錢的最大安全係數,//注意初始化的時候dp[0]=1,其他的設定成沒有訪問過//這裡為了好轉移,我將除了dp[0]之外的dp元素置為-1//轉移很好想,就是如下這個方程:for(int i=0;i<n;i++){for(int j=max_money;j>=w[i];j--){
Time of Update: 2018-12-04
今天悲劇的第一題沒看懂題,好吧,不會做,B題最簡單,放出來。 這題的思路實際上是並查集,先定義一個數組st表示現在的狀態,目標狀態是1,2,3,……,n,那麼,每次尋找i和i+v[i]和i-v[i]三個數,把他們合并,表示他們可以互相轉換,那麼用O(n)的複雜度掃一遍,可以把全部的元素屬於什麼集合預先處理出來,最後只要判斷st[i]和i是不是一個集合裡的就可以了。 今天無聊複習C++,封裝了個並查集的類,剛好用上。。。 My Code: #include <cstdio>using
Time of Update: 2018-12-04
這題是單調隊列的典型運用。 至於單調隊列,就是一個雙端隊列,在隊首(f)出隊,在隊尾(b)出隊入隊,我們要維護整個隊列的元素是單調的,比如,我們要動態查詢從左向右的區間的最小值,那麼我們就要在隊列中維護一個單調遞增的序列,從左向右枚舉,隊列的元素還有一個id值,代表這個元素在原序列中的位置,然後左邊的元素如果不在範圍內了,就判斷隊首的元素id是否是這個左邊的id,是的話就出隊,否則就不管。關於元素入隊,首先判斷入隊的元素是否大於隊尾的元素(保證隊列單調遞增),如果不大於,那麼彈出隊尾元素,直到隊