CodeForces 220(div 2)
悲剧的div2。。。。。
A
题意:在n * m的矩形平面直角坐标系中,从(x, y)可以到四个点(x - a, y - b),(x + a, y - b),(x - a, y + b),(x + a, y + b)。给定坐标(x, y)和a, b, n, m,求该点走到矩形顶点( (1, m), (n, 1), (n, m), (1, 1)中任意一个)最少需要多少步。如果走不到,返回-1。
解法:枚举一下走到哪个顶点就行了。关键是有两个trick,一个是不能走出矩形边界,另一个是比如(3, 2),a = b = 1走不到(1, 1)。注意特判就好了。
tag:水题, trick
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-12-18 23:33 4 * File Name: A.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <string> 10 #include <cmath> 11 #include <algorithm> 12 #include <vector> 13 #include <cstdlib> 14 #include <sstream> 15 #include <fstream> 16 #include <list> 17 #include <deque> 18 #include <queue> 19 #include <stack> 20 #include <map> 21 #include <set> 22 #include <bitset> 23 #include <cctype> 24 #include <ctime> 25 #include <utility> 26 27 using namespace std; 28 29 #define CLR(x) memset(x, 0, sizeof(x)) 30 #define PB push_back 31 #define SZ(v) ((int)(v).size()) 32 #define ALL(t) t.begin(),t.end() 33 #define INF 999999999999 34 #define zero(x) (((x)>0?(x):-(x))<eps) 35 #define out(x) cout<<#x<<":"<<(x)<<endl 36 #define tst(a) cout<<#a<<endl 37 #define CINBEQUICKER std::ios::sync_with_stdio(false) 38 39 const double eps = 1e-8; 40 const double PI = atan(1.0)*4; 41 const int maxint = 2147483647; 42 43 typedef vector<int> VI; 44 typedef vector<string> VS; 45 typedef vector<double> VD; 46 typedef pair<int, int> pii; 47 typedef long long int64; 48 49 inline int Mymod (int a, int b) {int x=a%b; if(x<0) x+=b; return x;} 50 51 int n, m, x, y, a, b; 52 int gao(int x, int y, int ta, int tb) 53 { 54 int da = abs(x - ta), db = abs(y - tb); 55 if (da % a) return maxint; 56 if (db % b) return maxint; 57 58 int t1 = da / a, t2 = db / b; 59 if (abs(t1-t2) & 1) return maxint; 60 if (t1 == t2) return t1; 61 if (t1 < t2){ 62 if (n < 2*a) return maxint; 63 return t2; 64 } 65 else{ 66 if (m < 2*b) return maxint; 67 return t1; 68 } 69 } 70 71 int main() 72 { 73 // freopen("a.in","r",stdin); 74 // freopen("a.out","w",stdout); 75 // std::ios::sync_with_stdio(false); 76 while (cin >> n >> m >> x >> y >> a >> b){ 77 int ans = min(gao(x, y, 1, 1), gao(x, y, 1, m)); 78 ans = min(ans, gao(x, y, n, m)); 79 ans = min(ans, gao(x, y, n, 1)); 80 if (ans == maxint) cout << "Poor Inna and pony!" << endl; 81 else cout << ans << endl; 82 } 83 return 0; 84 }
B
题意:给一个有'1' - '9'组成的字符串s,可以进行一种操作,就是如果s[i]-‘0’ + s[i+1]-‘0' == 9,可以在s中用'9'替换s[i]和s[i+1]。问在最终得到的字符串s含有9数量最多的前提下,最终操作完成后可能得到多少种字符串。s.size() <= 10^5。
解法:考虑连续几个和都为9的情况,比如34343,如果子串长度为偶数,则只有一种操作方法。否则,有(len+1) / 2种处理方法。每个子串的处理方法数相乘即为答案。
tag:水题
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-12-18 23:44 4 * File Name: B.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <string> 10 #include <cmath> 11 #include <algorithm> 12 #include <vector> 13 #include <cstdlib> 14 #include <sstream> 15 #include <fstream> 16 #include <list> 17 #include <deque> 18 #include <queue> 19 #include <stack> 20 #include <map> 21 #include <set> 22 #include <bitset> 23 #include <cctype> 24 #include <ctime> 25 #include <utility> 26 27 using namespace std; 28 29 #define CLR(x) memset(x, 0, sizeof(x)) 30 #define PB push_back 31 #define SZ(v) ((int)(v).size()) 32 #define ALL(t) t.begin(),t.end() 33 #define INF 999999999999 34 #define zero(x) (((x)>0?(x):-(x))<eps) 35 #define out(x) cout<<#x<<":"<<(x)<<endl 36 #define tst(a) cout<<#a<<endl 37 #define CINBEQUICKER std::ios::sync_with_stdio(false) 38 39 const double eps = 1e-8; 40 const double PI = atan(1.0)*4; 41 const int maxint = 2147483647; 42 43 typedef vector<int> VI; 44 typedef vector<string> VS; 45 typedef vector<double> VD; 46 typedef pair<int, int> pii; 47 typedef long long int64; 48 49 inline int Mymod (int a, int b) {int x=a%b; if(x<0) x+=b; return x;} 50 51 int64 two[100]; 52 int a[100005]; 53 54 int main() 55 { 56 // freopen("a.in","r",stdin); 57 // freopen("a.out","w",stdout); 58 // std::ios::sync_with_stdio(false); 59 two[0] = 1; 60 for (int i = 1; i < 63; ++ i) 61 two[i] = two[i-1] * 2; 62 63 string s; 64 while (cin >> s){ 65 int n = s.size(); 66 for (int i = 0; i < n; ++ i) 67 a[i] = s[i] - '0'; 68 69 int num = 1; 70 int64 ans = 1; 71 for (int i = 1; i < n; ++ i){ 72 if (a[i] + a[i-1] == 9) 73 num ++; 74 else{ 75 if (num > 1 && num & 1) ans *= (num/2+1); 76 num = 1; 77 } 78 } 79 if (num > 1 && num & 1) ans *= (num/2+1); 80 cout << ans << endl; 81 } 82 83 return 0; 84 }
C
题意:一个由四个字符——D,I,M,A——组成的n*m的矩阵中,能从写有D的格子走到I,I走到M,M走到A,A走回D。可以从任意写有D的格子开始,问最多能走多少组DIMA。
解法:简单DFS加记忆化。比赛的时候sb了。。。
tag:DFS, memorization
方法比较裸,比完以后我就没补这道题了。
D
题意:给一个数组an[],然后读入一串数并维护以个队列。若读到0或1,则将它放在队尾;若读到-1,则找到最大的i使得an[i] <= len(当前队列的长度),然后同时在队列中删除位置为an[0], an[1]....an[i]的元素。问最终得到的队列是什么。an.size() <= 10^6,读入的一串数最多10^6,1 <= an[i] <= 10^6。
解法:比赛的时候我写了个用并查集的方法,后来发现是错的。好像可以用后缀数组来做,O(n*logn*logn)的方法。不过我不会。。。。还有神牛写了O(n)的方法。
关键点在于:用扫一遍可以直到,每次将0/1放进去的时候,队列的长度是多少,也即是知道这个数放进去的位置在哪。又即是说,只要提前预处理出每个位置在放了数以后,需要多少个-1操作才能把这一位删掉,这个问题就能得到解决。至于具体操作细节,看代码。
tag:think, dp, good
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-12-24 14:19 4 * File Name: D.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <vector> 10 11 using namespace std; 12 13 #define clr0(x) memset(x, 0, sizeof(x)) 14 #define pb push_back 15 #define sz(v) ((int)(v).size()) 16 #define out(x) cout<<#x<<":"<<(x)<<endl 17 #define tst(a) cout<<a<<" " 18 const int inf = 2147483647 / 2; 19 const int N = 1000005; 20 typedef vector<int> vi; 21 22 int n, m; 23 int opt[N]; 24 int an[N], d[N], flag[N]; 25 26 int bin_search(int x) 27 { 28 int l = 0, r = m-1; 29 while (l <= r){ 30 int mid = (l + r) >> 1; 31 if (an[mid] <= x) l = mid + 1; 32 else r = mid - 1; 33 } 34 return r; 35 } 36 37 int main() 38 { 39 while (scanf ("%d%d", &n, &m) != EOF){ 40 clr0 (d); clr0 (flag); 41 for (int i = 0; i < m; ++ i) 42 scanf ("%d", &an[i]); 43 int idx = 0, p = 1, num = 0; 44 while (idx < m){ 45 if (!idx && p != an[0]) d[p] = inf; 46 else{ 47 if (p == an[idx]){ 48 d[p] = 1; 49 ++ num; ++ idx; 50 } 51 else d[p] = d[p-num] + 1; 52 } 53 ++ p; 54 } 55 for (int i = p; i <= 1000000; ++ i) 56 d[i] = d[i-num] + 1; 57 58 int len = 0; 59 for (int i = 0; i < n; ++ i){ 60 scanf ("%d", &opt[i]); 61 if (opt[i] == -1) len -= 1 + bin_search(len); 62 else flag[i] = d[++len]; 63 } 64 vi v; 65 int cnt = 0; 66 for (int i = n-1; i >= 0; -- i){ 67 if (opt[i] == -1) ++ cnt; 68 else if (flag[i] > cnt) v.pb (opt[i]); 69 } 70 71 if (!sz(v)) printf ("Poor stack!"); 72 else for (int i = sz(v)-1; i >= 0; -- i) 73 printf ("%d", v[i]); 74 printf ("\n"); 75 } 76 return 0; 77 }
E
没做。
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。