看是老家的中学出的题目,会不会可爱一点呢?
嗯,真可爱,可爱的我两道题文件都错了。
因为最近我把文件输入输出改成#ifndef和#endif的形式了,然后放在了一个函数里,结果敲板子的时候忘调用了……
鬼知道为啥我T1敲了上去。
T1 rps
期望得分:20
实际得分:40
看了看题,发现这其实构成了一棵满二叉树,但这好像并没有什么用。然后就开始想暴力,可惜的是暴力都不知道怎么写。随便看了看上个厕所,突然发现只要最后的胜者确定了,这个序列就是唯一的,仅仅是没排好序。于是我就开始枚举胜者,再分治判断,然后我就不知怎么的开始犯zz了:如果合法,就直接排序输出,然后break了!我当时不知怎么想的,认为合法的序列就一个,然后又担心时间复杂度,决定找一个就完事……更有乐的是,我排序的时候又怕时间不够,只比较了两个序列的前4个字符……
所以估分的时候就只敢保证送的那20分。
正解其实和我的思路一样:枚举最终胜者,判定是否合法,如果合法,就排完序存下来,最后从得到的三个序列中取字典序最小的。排序就像归并排序,所以复杂度O(3 * nlogn)。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = (1 << 20) + 5; 21 const int base = 100; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), last = ' '; 26 while(!isdigit(ch)) {last = ch; ch = getchar();} 27 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 28 if(last == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) x = -x, putchar('-'); 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 void MYFILE() 38 { 39 #ifndef mrclr 40 freopen("rps.in", "r", stdin); 41 freopen("rps.out", "w", stdout); 42 #endif 43 } 44 45 int r, p, s, n; 46 const char c[3] = {'P', 'R', 'S'}; 47 int num[3], a[maxn], ans[3][maxn]; 48 49 bool judge(int L, int R, int x) 50 { 51 if(L == R) 52 { 53 if(--num[x] < 0) return 0; 54 a[L] = x; return 1; 55 } 56 int mid = (L + R) >> 1; 57 return judge(L, mid, x) && judge(mid + 1, R, ++x > 2 ? 0 : x); 58 } 59 void rotate(int L, int R) //归并排序 60 { 61 if(L == R) return; 62 int mid = (L + R) >> 1; 63 rotate(L, mid); rotate(mid + 1, R); 64 bool flg = 0; 65 for(int i = L, j = mid + 1; i <= mid; ++i, ++j) 66 if(a[i] > a[j]) {flg = 1; break;} 67 if(flg) for(int i = L, j = mid + 1; i <= mid; ++i, ++j) 68 swap(a[i], a[j]); 69 } 70 71 void init() 72 { 73 num[0] = p; num[1] = r; num[2] = s; 74 } 75 76 void work(int x) 77 { 78 init(); 79 if(judge(1, n, x)) 80 { 81 rotate(1, n); 82 for(int i = 1; i <= n; ++i) ans[x][i] = a[i]; 83 } 84 } 85 86 int main() 87 { 88 MYFILE(); 89 r = read(), p = read(), s = read(); 90 n = r + p + s; 91 for(int i = 0; i < 3; ++i) ans[i][1] = 'Z'; 92 for(int i = 0; i < 3; ++i) work(i); 93 for(int i = 1; i <= n; ++i) //一下繁琐的代码其实就是在找三者中字典序最小的…… 94 { 95 int Min = ans[0][i], pos = 0, pos2 = ans[0][i]; 96 for(int j = 1; j < 3; ++j) 97 { 98 if(ans[j][i] < Min) Min = ans[j][i], pos = j; 99 if(ans[j][i] != pos2) pos2 = -1; 100 } 101 if(pos2 == -1) 102 { 103 for(int j = 1; j <= n; ++j) putchar(c[ans[pos][j]]); 104 enter; return 0; 105 } 106 } 107 printf("IMPOSSIBLE\n"); 108 return 0; 109 }