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 }
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 }
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 }
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 }
G. Jellyfish Nightmare
Unsolved.