哈哈哈哈第一次做ctsc的題超開心,感覺一下子就有檔次了許多。
這題的資料範圍對我這種不會算空間的蒟蒻就是個迷。
對於 100%的測試資料,輸入檔案的長度不超過 1100000 位元組
呵。做法:
①把所有作文庫連起來,每兩個中間用2隔開建sam
②作文串在sam上跑一跑,計算出以每乙個位置為結尾,最多能匹配多長。即,val[i]表示,s[1…i]中與作文庫能匹配的最長suffix的長度。
③由於這題的答案具有可二分性,所以二分乙個答案l進行檢驗。用dp去求最長覆蓋數即可(單調佇列優化一下)。
這裡給出使用單調佇列的充分性的證明:即是要證i-val[i]單調不減。
=> i + 1 - val[i + 1] ≥ i - val[i]
=> val[i + 1] ≤ val[i] + 1 顯然成立
這題我tle了一整天,愣是卡在90分。人家網上別的程式,最長時間的樣例才100多ms,我不算t的點,最大的就有將近700ms。反省了很久,發現是memset的鍋。我給單調佇列清了0,這樣做完全沒有必要。但是我是真的沒想到會這樣。畢竟dp就是乙個o(n)的,memset也是o(n)。這啟發我們,盡量想清楚再決定寫不寫有沒有意義。
code:(放心看吧,網上的幾組hack資料hack不掉我)
#include #include #define n 2300010
#include using namespace std;
int n, m; char s[n];
int ch[n][3], len[n], link[n];
int last, sz;
inline void sam_init()
inline void sam_extend(int c)
} last = cur;
}int val[n], f[n], q[n];
inline bool check(int x, int len1)
while(head <= tail && q[head] < i - val[i]) ++head;
if(head <= tail) f[i] = max(f[i], f[q[head]] - q[head] + i);
} return 10 * f[len1] >= 9 * len1;
}inline int read()
while(ch >= '0' && ch <= '9')
return x * f;
}int main()
for(int i = 1; i <= n; ++i)
val[i] = cur; r = max(r, val[i]);
} while(l <= r)
else r = mid - 1;
} printf("%d\n", ans);
} return 0;
}
CTSC2012 熟悉的文章
題目 好題啊 sam 單調佇列優化 dp 首先這個 l 滿足單調性真是非常顯然我們可以直接二分 二分之後套乙個 dp 就好了 設 dp i 表示到達 i 位置熟悉的文章的最大長度 有乙個非常顯然的 dp 方程 dp i max i j mid 同時 j 1,i 這個子串也得是模式串裡的乙個子串 對於...
ctsc2010 星際旅行
題意很簡單 給定一棵樹,問從根分別走到每個節點的最長路程,其中每個點給定lim,即最多從該點出發lim次,保證lim大於等於該點的度數。特別 鳴謝 ldl在他的模擬題中出了這道題。當題解講這要用樹形dp解網路流模型時,都被驚異了,完全沒有想到網路流,也完全沒有必要網路流,atm在考場上直接有樹形dp...
CTSC2018 混合果汁
為何要用整體二分,整體二分應該怎樣二分,和 poi2011 met meteors十分相像,這裡就不再重複。那麼對於乙個顧客來講,如果當前的區間總份數小於他想要的份數,或者是區間最小 大於他能接受的最大 就把該顧客劃分到右區間,如若滿足則劃分到左區間。想要和 poi2011 met meteors一...