Mail.Ru Cup 2018 Round 2 Solution

A. Metroc++

Solved.數組

題意:ide

有兩條鐵軌,都是單向的,一條是從左往右,一條是從右往左,Bob要從第一條軌道的第一個位置出發,Alice的位置處於第s個位置,有火車會行駛在鐵軌上,一共有n個站點,1表示火車會在該站點停下,0表示不會,求Bob可否到達地s個位置(到達任意一邊便可)spa

思路:code

若是第一條鐵軌的第一個位置爲0,或者第s個位置的兩條鐵軌都不停,那麼答案顯然是$"No"$htm

再考慮第一條鐵軌上全部爲1的位置均可以到達blog

再考慮兩條軌道是否有同一個站點都都會停下的,那麼就能夠到達第二條軌道,而且該站點的左邊的會停下的站點均可以到達it

再判斷一下s站點有沒有被標記便可。event

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 1010
 5 int n, s, a[N], b[N];
 6 int vis[N];
 7 
 8 bool solve()
 9 {
10     if (a[1] == 0) return false;
11     if (a[s] == 0 && b[s] == 0) return false;
12     for (int i = 1; i <= n; ++i) if (a[i]) vis[i] = 1;
13     bool flag = false;
14     for (int i = n; i >= 1; --i)
15     {
16         if (a[i] && b[i]) flag = 1;
17         if (flag && b[i]) vis[i] = 1; 
18     }
19     return vis[s];
20 }
21 
22 int main()
23 {
24     while (scanf("%d%d", &n, &s) != EOF)
25     {
26         memset(vis, 0, sizeof vis);
27         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
28         for (int i = 1; i <= n; ++i) scanf("%d", b + i);
29         puts(solve() ? "YES" : "NO");    
30     }
31     return 0;
32 }
View Code

 

 

B. Alice and Hairdresserclass

Solved,

題意:

Alice有$n根頭髮,只有長度 > l 的頭髮才須要減,而且有相鄰多根頭髮的長度都 > l,那麼這幾根能夠一刀剪掉$

如今有兩種操做,第一種是詢問Alice若是要剪頭髮,最少須要減幾刀,第二種是第$p$根頭髮增長了$d$的長度。

思路:

頭髮增長時,若是這根頭髮已經$ > l 了$ 那麼不須要操做

反之,則判斷一下,左右兩邊的頭髮長度

若是左右兩邊頭髮長度都$> l$ 那麼下剪刀的次數 - 1  由於左右兩邊原本是兩個連通塊,如今連成一個。

若是有一邊$ > l$ 有一邊不是,那麼下剪刀次數不變

若是兩邊都$ < l$ 那麼下剪刀次數+1

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 100010
 6 int n, m, res; 
 7 ll l, a[N];
 8 
 9 int main()
10 {
11     while (scanf("%d%d%lld", &n, &m, &l) != EOF)
12     {
13         res = 0;
14         for (int i = 1; i <= n; ++i) 
15         {
16             scanf("%lld", a + i);
17             if (a[i] > l && a[i - 1] <= l) ++res; 
18         }
19         for (int i = 1, t, p, d; i <= m; ++i)
20         {
21             scanf("%d", &t);
22             if (t == 0) printf("%d\n", res);
23             else 
24             {
25                 scanf("%d%d", &p, &d);
26                 if (a[p] <= l && a[p] + d > l)  
27                 {
28                     if (a[p - 1] > l && a[p + 1] > l) --res;
29                     else if (a[p - 1] > l || a[p + 1] > l);
30                     else ++res;                    
31                 }
32                 a[p] += d;  
33             }
34         }
35     }
36     return 0;
37 }
View Code

 

 

C. Lucky Days

Upsolved.

題意:

定義一個三元組$<l, r, t>$ 表示一個週期爲$t$,第$[l, r]$天裏面是幸運天,如今給出$Alice 和 Bob$的兩個三元組,求兩人最長的連續相同的幸運天數。

 思路:

考慮兩我的的起點之差是 $gcd(ta, tb)$ 用一我的的起點去逼近另外一我的的起點,而後求一下答案。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 ll la, lb, ra, rb, ta, tb;
 6 
 7 ll gcd(ll a, ll b)
 8 {
 9     return b ? gcd(b, a % b) : a;
10 }
11 
12 ll calc(ll la, ll ra, ll lb, ll rb)
13 {
14     return max(0ll, min(ra, rb) - max(la, lb) + 1);  
15 }
16     
17 int main()
18 {
19     while (scanf("%lld%lld%lld", &la, &ra, &ta) != EOF)
20     {
21         scanf("%lld%lld%lld", &lb, &rb, &tb);
22         if (la > lb) 
23         {
24             swap(la, lb); 
25             swap(ra, rb);
26             swap(ta, tb);
27         }
28         ll g = gcd(ta, tb);
29         ll gap = ra - la;
30         la += ((lb - la) / g) * g;
31         ra = la + gap;
32         printf("%lld\n", max(calc(la, ra, lb, rb), calc(la + g, ra + g, lb, rb)));
33     }
34     return 0;
35 }
View Code

 

 

D. Refactoring

Unsolved.

 

E. Segments on the Line

Unsolved.

 

F. Tree and XOR

Upsolved.

題意:

在一棵樹種,一共有$n^2$個任意兩點間的簡單路徑異或和,求第k大。

 思路:

顯然,路上任意兩點路徑異或和就是兩個點到根的異或和再異或

再考慮求第k大,能夠二分,而後去找到有多少個比這個數小的數,若是$<= k 那麼這個數就可能能夠做爲答案$

但這樣的過程是$O(n{log^n}^2)$,顯然不行

可是其實能夠直接一位一位考慮,從高位到低位逐位肯定,枚舉當前爲是否爲1,若是爲1,那麼異或後當前爲爲0的都是比當前數小的數,逐步肯定下去便可。

可是注意到,這個過程能夠用$01Trie 完成,可是完整的01Trie空間開不下$

又考慮咱們每一次肯定的時候,只會用到上一層和當前層的狀態,全部用滾動數組便可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 1000010
 6 int n, rt[N], prt[N], ch[N][2], num[N], cnt;  
 7 ll w[N], k;
 8 
 9 void init()
10 {
11     memset(num, 0, sizeof num);
12     memset(ch, 0, sizeof ch);
13 }
14 
15 int main()
16 {
17     while (scanf("%d%lld", &n, &k) != EOF)
18     {
19         init();
20         for (int i = 2, p; i <= n; ++i)
21         {
22             scanf("%d%lld", &p, w + i);
23             w[i] ^= w[p];
24         }
25         ll res = 0;
26         for (int i = 1; i <= n; ++i) rt[i] = prt[i] = 1; cnt = 1;
27         for (int s = 62; s >= 0; --s)
28         {
29             for (int i = 1; i <= cnt; ++i) ch[i][0] = ch[i][1] = num[i] = 0; cnt = 1;
30             for (int i = 1; i <= n; ++i)
31             {
32                 int id = (w[i] >> s) & 1;
33                 if (!ch[rt[i]][id]) ch[rt[i]][id] = ++cnt;
34                 rt[i] = ch[rt[i]][id];
35                 ++num[rt[i]];
36             }    
37             ll sum = 0;
38             for (int i = 1; i <= n; ++i)
39             {
40                 int id = (w[i] >> s) & 1;
41                 sum += num[ch[prt[i]][id]];
42             }
43             if (sum < k)
44             {
45                 res |= 1ll << s;
46                 k -= sum;
47                 for (int i = 1; i <= n; ++i)
48                 {
49                     int id = (w[i] >> s) & 1;
50                     prt[i] = ch[prt[i]][id ^ 1];
51                 }
52             }
53             else
54             {
55                 for (int i = 1; i <= n; ++i)
56                 {
57                     int id = (w[i] >> s) & 1;
58                     prt[i] = ch[prt[i]][id];
59                 }
60             }
61         }
62         printf("%lld\n", res);
63     }    
64     return 0;
65 }
View Code

 

G. Jellyfish Nightmare

Unsolved.

相關文章
相關標籤/搜索