出题人全是thu的,时间也很友好(晚上八点)。赛前确定是中国场(数据结构场)无疑了。
结果开题之后发现根本不是这么一回事……虽然题目区分度挺高的。
题目链接:https://codeforces.com/contest/1173
A:
给定x,y,z三个数,代表有三堆人投票。一堆人投赞成票,一堆人投反对票,还有一堆人不确定投哪一票(不会弃权)。问最终结果是否可确定且为什么结果。
傻逼题。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson curpos<<1 15 #define rson curpos<<1|1 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 int x, y, z; 21 22 int main() { 23 cin >> x >> y >> z; 24 int ans = x - y; 25 if (!ans && !z) puts("0"); 26 else if (ans + z > 0 && ans - z > 0) puts("+"); 27 else if (ans + z < 0 && ans - z < 0) puts("-"); 28 else puts("?"); 29 return 0; 30 }
B:
给定n,问能构造多小的n*n矩形,使得能填入n个数字(从1到n,每个数字只出现一次)。而且对于第i个数字和第j个数字,满足abs(Xi-Xj)+abs(Yi-Yj)>=abs(i-j)。
没啥好说的,贪心就完事了。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson curpos<<1 15 #define rson curpos<<1|1 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 int n; 21 22 int main() { 23 cin >> n; 24 cout << n / 2 + 1 << endl; 25 rep1(i, 1, n) cout << (i + 1) / 2 << " " << i / 2 + 1 << endl; 26 return 0; 27 }
C:
有2n张牌,其中n张是空的,另外n张被1到n共n个数字标记。现在把这2n张牌打乱,并把n张牌叠起来放在桌上,另外n张放到手里。唯一操作:挑选手里的任意某张牌,放到牌堆底部,并把牌堆顶部的一张牌放到手中。
问最少要多少步使得牌堆里的牌都是被标记的牌,且自底向上有序(从大到小)。
贪心。看手中的牌是没有用的,不停判断牌堆中的牌状态即可。首先尝试不打空白牌能否完成,若不能,则必然是打出若干张空白牌之后就再也不打空白牌。
记录每张牌在牌堆的初始位置pos[i],若不在则为0。显然ans=max(pos[i]-i+1+n)。
因为我们的最终目标是把1-n叠在桌子上且有序。那么存在牌k,在经过操作后,使得[1,2,...,k]在牌堆的底端,并且接下来的操作只用标号为[k+1,....,n]的牌,将其依次插入牌堆的底端。这种情况下,答案就为pos[k]+1+n-k。其中pos[k]+1是将牌 k 插入牌堆底端需要的最小操作,n-k是将[k+1,....,n]依次插入牌堆的最小操作。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(pos,b) sort(pos+1,pos+1+b) 9 #define rep1(i,pos,b) for(int i=pos;i<=b;++i) 10 #define rep0(i,pos,b) for(int i=pos;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson curpos<<1 15 #define rson curpos<<1|1 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 2e5 + 10; 21 int n, pos[maxn], x, flag = 0; 22 23 int main() { 24 scanf("%d", &n); 25 rep1(i, 1, n) scanf("%d", &x); 26 rep1(i, 1, n) { 27 scanf("%d", &x); 28 if (x > 0) pos[x] = i; // record sequence 29 if (x == 1) flag = 1; // start sign 30 else { 31 if (flag && x == flag + 1) flag++; // start and in increasing order 32 else flag = 0; 33 } 34 } 35 if (flag) { // special judge 36 int flag2 = 1; 37 rep1(i, flag + 1, n) 38 if (pos[i] >= i - flag) flag2 = 0; 39 if (flag2) { 40 return printf("%d ", n - flag), 0; 41 } 42 } 43 int tmp = 0; 44 rep1(i, 1, n) tmp = max(tmp, pos[i] - i + 1); 45 printf("%d ", n + tmp); 46 return 0; 47 }
D:
给定一棵树,把树的所有节点放到圆上,使得所有的边不相交,问方案数。
盲猜了一个度数的结论就过了。因为方案数由点的度数决定,肯定是每条边的两个端点度数累乘。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson curpos<<1 15 #define rson curpos<<1|1 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 2e5 + 10, mod = 998244353; 21 int n, a[maxn]; 22 23 int main() { 24 scanf("%d", &n); 25 ll ans = n; 26 rep1(i, 1, n - 1) { 27 int x, y; scanf("%d%d", &x, &y); 28 ans = ans * (++a[x]) % mod * (++a[y]) % mod; 29 } 30 printf("%lld ", ans); 31 return 0; 32 }
E:
看了一眼,图相关的概率dp题,溜了。而且题解推导很复杂……
easy和hard都不会。
F:
一个有点玄妙的模拟题。给定一个n*n的矩阵,一个人只能从第一排或第一列的格子进入矩阵,且进入后前进方向不能改变。矩阵中有若干对传送门,走到传送门上会传送到另一个传送门并保持原来的方向继续走。
给定每个入口必须走到的出口(就是一个入口对应一个出口),问矩阵中的传送门该如何放置。
显然架设一对传送门后,所有经过这两个格点的路径都会受到影响,所以1~n枚举出口使得改变后的行列后移,变得有序。故传送门架设的顺序是依次往右下方向,因为遍历1出口时,需要经过其他行的路径经过传送门已经默认从1开始。自然不会破坏前面架设门的相对关系。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson curpos<<1 15 #define rson curpos<<1|1 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 1e3 + 10; 21 int n, x, y, a[maxn], b[maxn], tot = 0; 22 struct Door { 23 int a, b, c, d; 24 Door() {} 25 Door(int x, int y, int p, int q): a(x), b(y), c(p), d(q) {} 26 }; 27 Door door[maxn]; 28 29 int main() { 30 scanf("%d", &n); 31 rep1(i, 1, n) scanf("%d", &a[i]); 32 rep1(i, 1, n) scanf("%d", &b[i]); 33 rep1(i, 1, n) { 34 if (a[i] == i && b[i] == i) continue; 35 rep1(j, i, n) 36 if (a[j] == i) { 37 swap(a[i], a[j]); 38 x = j; 39 break; 40 } 41 rep1(j, i, n) 42 if (b[j] == i) { 43 swap(b[i], b[j]); 44 y = j; 45 break; 46 } 47 door[++tot] = Door(x, i, i, y); 48 } 49 printf("%d ", tot); 50 rep1(i, 1, tot) printf("%d %d %d %d ", door[i].a, door[i].b, door[i].c, door[i].d); 51 return 0; 52 }