國慶摸底測試

考了上下午兩場六題,應該是模擬noip的。數組

第三題過於難,考的奇葩數論。T5T6都簡單了些。ide

得分100 + 100 + 40 + 100 + 0 + 30 = 370大數據

簡單分析一下,主要失誤在於T5。優化

三個100就不說,T3盡力了。T6是相似魔法森林的一道題,是個刪邊維護生成樹的套路,沒想出來。spa

T5顯然在個人能力範圍以內,爆0。code

 


大意:一個寂寞堆的性質是:子節點不大於父節點 && 左子樹每一個點都不大於柚子樹。blog

給你一個滿二叉樹,問至少改變幾個數能使它變成寂寞的。ip

當時我滿腦子都是樹形DP,區間DP,可是怎麼想都不對...get

而後發現能夠把每一個點之間的關係作成圖,不知足的條件做爲邊,而後跑最小點覆蓋。string

而後發現這TM不是二分圖啊......

而後又去想怎麼在這個二叉樹上面DP,沒搞出來......

而後準備把小數據特判得30分,可是由於我愚蠢的輸出了樹中節點個數致使這30分也涼了。

正解:注意上面,把每一個點的關係作成圖。

實際上這個圖的拓撲序惟一,由於任意兩個點的大小均可以藉由lca得出。

因此按照逆拓撲序求最長不升子序列就OK了。

拓撲序在這裏就是中右左序。

 


接着講一下T6的套路:題意:

給你n個點,q次操做,有加邊,刪邊,查詢連通性。

且每兩點的邊至多隻會被加/刪一次。

n<=400,q<=100000

解:

考慮暴力,顯然是每次DFS。這樣作是qm的,m上限有n²,因此是qn²,能拿30分。

而後咱們發現這個n很小,有什麼用呢?不知道。

而後咱們考慮轉圖爲樹,那麼只需維護生成樹便可。

維護哪些生成樹呢?刪邊時間最靠後的!

由於若是走一些刪邊時間靠前的邊能到達,那麼這個生成樹也必定可達。

若是這個都不可達,那麼刪邊時間靠前的更不可達。

而後,遍歷樹是n的,因而時間被壓到了qn,4e7能夠過。

刪邊的時候若是還在就刪。加邊的時候,若是連通就去掉刪除時間最先的。查詢直接DFS。

實際操做上,因爲是森林因此不須要vis數組。記錄父親便可。

用vector代替鄰接表存邊,以節省遍歷被刪的邊的時間,作到O(n)。

  1 #include <cstdio>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <cstring>
  5 
  6 const int N = 405, INF = 0x3f3f3f3f, M = 100010;
  7 
  8 std::vector<int> G[N];
  9 char c[M][10];
 10 int del[N][N], da, db, xx[M], yy[M];
 11 
 12 bool DFS(int x, int t, int f) {
 13     //printf("DFS : x = %d \n", x);
 14     if(x == t) {
 15         return 1;
 16     }
 17     for(int i = 0; i < G[x].size(); i++) {
 18         //printf("G[%d][%d] = %d \n", x, i, G[x][i]);
 19         int y = G[x][i];
 20         if(y != f && DFS(y, t, x)) {
 21             return 1;
 22         }
 23     }
 24     return 0;
 25 }
 26 
 27 bool getmin(int x, int T, int f) {
 28     if(x == T) {
 29         return 1;
 30     }
 31     for(int i = 0; i < G[x].size(); i++) {
 32         int y = G[x][i];
 33         if(y == f) {
 34             continue;
 35         }
 36         int t = getmin(y, T, x);
 37         if(t && (del[x][y] <= del[da][db])) { // error : <
 38             da = x;
 39             db = y;
 40         }
 41         if(t) {
 42             return 1;
 43         }
 44     }
 45     return 0;
 46 }
 47 
 48 int main() {
 49     freopen("fool3.in", "r", stdin);
 50     freopen("my.out", "w", stdout);
 51     int n, m;
 52     scanf("%d%d", &n, &m);
 53     int x, y;
 54     memset(del, 0x3f, sizeof(del));
 55     for(int i = 1; i <= m; i++) {
 56         scanf("%s", c[i]);
 57         scanf("%d%d", &xx[i], &yy[i]);
 58         if(c[i][0] == 'd') {
 59             del[xx[i]][yy[i]] = del[yy[i]][xx[i]] = i;
 60         }
 61     }
 62 
 63     for(int i = 1; i <= m; i++) {
 64         x = xx[i];
 65         y = yy[i];
 66         if(c[i][0] == 'd') { // del
 67             for(int i = 0; i < G[x].size(); i++) {
 68                 if(G[x][i] == y) {
 69                     std::swap(G[x][i], G[x][G[x].size() - 1]);
 70                     G[x].pop_back();
 71                     break;
 72                 }
 73             }
 74             for(int i = 0; i < G[y].size(); i++) {
 75                 if(G[y][i] == x) {
 76                     std::swap(G[y][i], G[y][G[y].size() - 1]);
 77                     G[y].pop_back();
 78                     break;
 79                 }
 80             }
 81         }
 82         else if(c[i][1] == 'd') { // add
 83             getmin(x, y, 0);
 84             if(del[x][y] <= del[da][db]) {
 85                 if(da) {
 86                     da = db = 0;
 87                     continue;
 88                 }
 89                 G[x].push_back(y);
 90                 G[y].push_back(x);
 91                 continue;
 92             }
 93             for(int i = 0; i < G[da].size(); i++) {
 94                 if(G[da][i] == db) {
 95                     std::swap(G[da][i], G[da][G[da].size() - 1]);
 96                     G[da].pop_back();
 97                     break;
 98                 }
 99             }
100             for(int i = 0; i < G[db].size(); i++) {
101                 if(G[db][i] == da) {
102                     std::swap(G[db][i], G[db][G[db].size() - 1]);
103                     G[db].pop_back();
104                     break;
105                 }
106             }
107             da = db = 0;
108             G[x].push_back(y);
109             G[y].push_back(x);
110         }
111         else { // ask
112             printf("%d\n", DFS(x, y, 0));
113         }
114     }
115 
116     return 0;
117 }
AC代碼

時間卡的很緊,0.9s過的大數據。能夠用LCT優化到qlog²n,那就是魔法森林了。

總結:初級的題沒有失誤很好;T3,T5這種難度的儘可能爭取滿分,沒把握就面向數據,反正部分分必定要拿穩。若是時間還多,暴力又打完了,檢查一萬遍了,儘可能爆肝正解。說不定靈光一閃就A了;不要太自信,對拍是必要的。沒有對拍就手造10min的數據。

[update]:T3簡直天秀,真·神奇解法,天下第一。

以後填坑。

相關文章
相關標籤/搜索