A. Ascending Photo
题意:给你一个长度为n的整数序列a[1-n],n不超过1e6。让你把它切成最少的片段,使得切完之后重排片段可以使序列不严格递增。问最少切几段。
观察:
首先可以离散化一下,把所有的值map到m个数[1,2,...,m],m <= n <= 1e6。然后我们可以线性扫一遍,把相邻且数字相同的位置连在一起形成连通分量,因为可以发现,连续的相同数字不需要被切开(如果有被切开,可以把切口平移至左端或者右端,并且不破坏答案成立)。
然后我们就可以按照数值从小到大考虑每个联通分量前面切不切了。比如现在枚举到v,v对应的有一个区间[L1, R1]。我们看一下a[L1-1]是不是 v-1。如果a[L1-1] = v-1, 我们可以少切(a[L1-1], a[L1])这一刀。如果对于一个v,有多个区间满足上述条件,我们至多只能少切其中的一个。
还有一个比较特殊的情况,就是,对于a[L1-1] = v-1, 我们想要少切(a[L1-1], a[L1])这一刀,但是a[L1-1]所对应的片段与其前面一个值为v-2的片段已经少切了一刀,我们要判断一下(a[L1-1], a[L1])可不可以切。比如 a[1-4] = [3 2 3 4],a[2]前面切一刀,然后a[3] = 3, a[2] = 2, 我们可以少切(a[2], a[3])这一刀,再看a[4]。虽然a[3] = 3, a[4] = 4,但是我们不能少切(a[3], a[4])这一刀,因为那样的话会形成(a[2] a[3] a[4]) = (2 3 4),剩下a[1]=3,没有办法重排。所以对于(a[2], a[3]),我们在决定要少切这刀的时候,发现这个v=3的片段不是唯一的(即外面还有别的3的片段),那么我们就要求这个片段之后v=4的片段不能少切。
再考虑一个例子,a[1-5] = [2 3 4 2 3], 我们发现(a[1], a[2]) = (a[4], a[5]) = (2, 3),都可以少切一刀,该怎么选择呢?方法就是不用选择。一旦对于一种(v-1, v)有不少与2种合法的位置,那么就一定可以选择其中的位置少切一刀,使得对后面的操作没有影响。比如,a[1-5] = [2 3 4 2 3], 我们先少切(a[1], a[2])这一刀,后来发现(a[2], a[3])本来也可以少切的,那么我们一开始就不要少切(a[1] a[2]),反而去少切(a[4] a[5]), 这样就可以顺利的少切(a[2] a[3])了。
code:
1 /* 2 by skydog 3 */ 4 #include <iostream> 5 #include <cstdio> 6 #include <vector> 7 #include <utility> 8 #include <algorithm> 9 #include <cmath> 10 #include <cstring> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <deque> 16 #include <cassert> 17 #include <list> 18 using namespace std; 19 typedef long long ll; 20 typedef pair<int, int> ii; 21 typedef pair<ll, ll> l4; 22 23 #define mp make_pair 24 #define pb push_back 25 #define db(x) cerr << #x << " = " << x << endl 26 27 typedef unsigned long long ull; 28 const int maxn = 1e6+1; 29 int a[maxn], b[maxn], vis[maxn], n; 30 vector<ii> interval[maxn]; 31 32 int main() 33 { 34 scanf("%d", &n); 35 for (int i = 1; i <= n; ++i) 36 scanf("%d", a+i); 37 memcpy(b+1, a+1, n*sizeof(int)); 38 sort(b+1, b+1+n); 39 int m = unique(b+1, b+1+n)-(b+1); 40 for (int i = 1; i <= n; ++i) 41 a[i] = lower_bound(b+1, b+1+m, a[i])-b; 42 a[0] = m+1; 43 for (int i = 1, nxt; i <= n; i = nxt) 44 { 45 nxt = i+1; 46 while (nxt <= n && a[nxt] == a[i]) 47 ++nxt; 48 interval[a[i]].pb(mp(i, nxt-1)); 49 i = nxt; 50 } 51 int ans = -1; //suppose we need to cut a[0] and a[1]. 52 for (int i = 1; i <= n; ++i) 53 { 54 int cnt = 0, tail; 55 for (auto e : interval[i]) 56 { 57 ++ans; 58 if (a[e.first-1] == i-1) 59 { 60 if (vis[e.first-1]); 61 else 62 { 63 ++cnt; 64 tail = e.second; 65 } 66 } 67 } 68 if (cnt == 0); 69 else 70 { 71 --ans; 72 if (interval[i].size() != 1 && cnt == 1) 73 vis[tail] = true; 74 } 75 } 76 printf("%d\n", ans); 77 } 78 // 12 1 2 2 3 3 1 2 3 4 1 2 3
WA:没有考虑到什么时候不能少切。
B. Boss Battls
题意:
观察:看样例猜出答案应该是max(1, n-2)。也可以考虑最坏情况,用环形[0, n-1]表示圆环,假设我们是在0的位置,为了堵住boss,我们沿着顺时针轰炸,且每次隔一格。然后最差情况boss起初在n-2的位置,和我们同方向运动。
code:
1 /* 2 by skydog 3 */ 4 #include <iostream> 5 #include <cstdio> 6 #include <vector> 7 #include <utility> 8 #include <algorithm> 9 #include <cmath> 10 #include <cstring> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <deque> 16 #include <cassert> 17 #include <list> 18 using namespace std; 19 typedef long long ll; 20 typedef pair<int, int> ii; 21 typedef pair<ll, ll> l4; 22 23 #define mp make_pair 24 #define pb push_back 25 #define db(x) cerr << #x << " = " << x << endl 26 27 int main() 28 { 29 int n; 30 scanf("%d", &n); 31 printf("%d\n", max(1, n-2)); 32 }
WA:
C. Connect the Dots
题意:
观察:
code:
WA:
D. Dunglish
题意:
观察:
code:
1 /* 2 by skydog 3 */ 4 #include <iostream> 5 #include <cstdio> 6 #include <vector> 7 #include <utility> 8 #include <algorithm> 9 #include <cmath> 10 #include <cstring> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <deque> 16 #include <cassert> 17 #include <list> 18 using namespace std; 19 typedef long long ll; 20 typedef pair<int, int> ii; 21 typedef pair<ll, ll> l4; 22 23 #define mp make_pair 24 #define pb push_back 25 #define db(x) cerr << #x << " = " << x << endl 26 27 map<string, ll> ma[2]; 28 map<string, string> translate; 29 vector<string> res; 30 inline int tag(const string&str) 31 { 32 return str[0] == ‘c‘; 33 } 34 int main() 35 { 36 ios::sync_with_stdio(false); 37 cin.tie(0); 38 int n, m; 39 cin >> n; 40 res.resize(n); 41 for (auto &e : res) 42 cin >> e; 43 cin >> m; 44 for (int i = 0; i < m; ++i) 45 { 46 string a, b, c; 47 cin >> a >> b >> c; 48 translate[a] = b; 49 ma[tag(c)][a] += 1; 50 } 51 ll tot = 1, correct = 1; 52 for (const auto &e : res) 53 { 54 correct *= ma[1][e]; 55 tot *= (ma[0][e] + ma[1][e]); 56 } 57 if (tot == 1) 58 { 59 for (int i = 0; i < n; ++i) 60 cout << translate[res[i]] << (i==n-1?‘\n‘:‘ ‘); 61 cout << (correct?"correct":"incorrect") << ‘\n‘; 62 } 63 else 64 { 65 cout << correct << " correct\n"; 66 cout << tot-correct << " incorrect\n"; 67 } 68 }
WA:
E. English Restaurant
题意:
观察:
code:
WA:
F. Factor-Free Tree
题意:
观察:
code:
WA:
G. Glyph Recognition
题意:
观察:
code:
WA:
H. High Score
题意:
观察:
code:
WA:
I. Installing Apps
题意:
观察:
code:
WA:
J. Juggling Toupe
题意:
观察:
code:
WA:
K. Knockout Tourmanent
题意:
观察:
code:
WA: