最后一场多校打得一般般。
题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=857
C:
递推概率水题。
1 /* Codeforces Contest 2019_mutc_10 2 * Problem C 3 * Au: SJoshua 4 */ 5 #include6 #include 7 #include <string> 8 #include 9 #include 10 #include 11 12 using namespace std; 13 14 const double eps = 1e-9; 15 16 int main(void) { 17 int T; 18 scanf("%d", &T); 19 while (T--) { 20 int n; 21 scanf("%d", &n); 22 vector <double> p(n); 23 for (int i = 0; i < n; i++) 24 scanf("%lf", &p[i]); 25 sort(p.begin(), p.end(), greater <double> ()); 26 double a = 1.0, b = 0.0, c = 0.0; 27 for (int i = 0; i < n; i++) { 28 double nxt = b * (1 - p[i]) + a * p[i]; // P of pick current gift 29 if (nxt - b > eps) { 30 a = a * (1 - p[i]); 31 b = nxt; 32 } 33 } 34 printf("%.9f\n", b); 35 } 36 return 0; 37 }
E:
对每个数对以x为关键字从小到大排序。枚举所有x,对于xi,找出最近的yi。用数据结构维护即可。复杂度O(nlogn)。
1 /* Codeforces Contest 2019_mutc_10 2 * Problem E 3 * Au: SJoshua 4 */ 5 #include <set> 6 #include
I:
BFS水题。
1 /* Codeforces Contest 2019_mutc_10 2 * Problem I 3 * Au: SJoshua 4 */ 5 #include6 #include 7 #include 8 #include <string> 9 #include 10 11 using namespace std; 12 13 bool board[2002][2002]; 14 int n, m, q; 15 16 const int movement[4][2] = { 17 {0, 1}, {0, -1}, {1, 0}, {-1, 0} 18 }; 19 20 struct pos { 21 int x, y; 22 }; 23 24 int solve(int x, int y) { 25 int ans = 0; 26 if (board[x][y]) { 27 queue q; 28 q.push({x, y}); 29 while (!q.empty()) { 30 auto t = q.front(); 31 q.pop(); 32 if (!board[t.x][t.y]) { 33 continue; 34 } 35 ans++; 36 board[t.x][t.y] = 0; 37 for (int i = 0; i < 4; i++) { 38 int nx = t.x + movement[i][0], ny = t.y + movement[i][1]; 39 if (1 <= nx && nx <= n && 1 <= ny && ny <= m && board[nx][ny]) { 40 if ((!board[nx + 1][ny] || !board[nx - 1][ny]) && (!board[nx][ny - 1] || !board[nx][ny + 1])) { 41 q.push({nx, ny}); 42 } 43 } 44 } 45 } 46 } 47 return ans; 48 } 49 50 int main(void) { 51 int T; 52 scanf("%d", &T); 53 while (T--) { 54 scanf("%d %d %d", &n, &m, &q); 55 for (int i = 0; i <= n + 1; i++) { 56 for (int j = 0; j <= m + 1; j++) { 57 board[i][j] = true; 58 } 59 } 60 while (q--) { 61 int x, y; 62 scanf("%d %d", &x, &y); 63 printf("%d\n", solve(x, y)); 64 } 65 } 66 return 0; 67 }
K:
做法略像之前牛客多校第四场C。对于每个a[i],计算出在满足区间内元素unique的前提下,往左往右能到的最大区间。
考虑启发式分治,对于当前区间,找到最大值所在位置并记为mid并看mid是更靠左还是靠右。若更靠左,则枚举左区间内的值作为端点,计算对右区间的贡献;反之同理。
1 // 数符合条件的区间个数,满足区间max-k<=区间长度 2 /* basic header */ 3 #include4 /* define */ 5 #define ll long long 6 #define dou double 7 #define pb emplace_back 8 #define mp make_pair 9 #define sot(a,b) sort(a+1,a+1+b) 10 #define rep1(i,a,b) for(int i=a;i<=b;++i) 11 #define rep0(i,a,b) for(int i=a;i 12 #define eps 1e-8 13 #define int_inf 0x3f3f3f3f 14 #define ll_inf 0x7f7f7f7f7f7f7f7f 15 #define lson (curpos<<1) 16 #define rson (curpos<<1|1) 17 /* namespace */ 18 using namespace std; 19 /* header end */ 20 21 const int maxn = 3e5 + 10; 22 23 struct Node { 24 int maxx, pos; 25 } segt[maxn << 2]; 26 int n, k, a[maxn], vis[maxn], pre[maxn], suf[maxn]; 27 28 void maintain(int curpos) { 29 segt[curpos].maxx = max(segt[lson].maxx, segt[rson].maxx); 30 segt[curpos].pos = segt[lson].maxx > segt[rson].maxx ? segt[lson].pos : segt[rson].pos; 31 } 32 33 void build(int curpos, int curl, int curr) { 34 if (curl == curr) { 35 segt[curpos].maxx = a[curl]; 36 segt[curpos].pos = curl; 37 return; 38 } 39 int mid = curl + curr >> 1; 40 build(lson, curl, mid); build(rson, mid + 1, curr); 41 maintain(curpos); 42 } 43 44 int query(int curpos, int curl, int curr, int ql, int qr) { 45 if (ql <= curl && curr <= qr) 46 return segt[curpos].pos; 47 int mid = curl + curr >> 1, lpos = -1, rpos = -1; 48 if (ql <= mid) lpos = query(lson, curl, mid, ql, qr); 49 if (mid < qr) rpos = query(rson, mid + 1, curr, ql, qr); 50 if (lpos == -1) return rpos; 51 else if (rpos == -1) return lpos; 52 else return a[lpos] > a[rpos] ? lpos : rpos; 53 } 54 55 void query(int l, int r, ll &ans) { 56 if (l > r) return; 57 int mid = query(1, 1, n, l, r), len = max(1, a[mid] - k); // mid是区间[l,r]最大值的位置,len是最小长度 58 if (mid - l <= r - mid) { // 最大值位置更靠左时,枚举最大值左侧元素作为区间左端点 59 for (int i = l; i <= mid; i++) { // 枚举左端点到mid的每个位置,暴力计算对右区间的贡献 60 int L = max(mid, i + len - 1), R = min(pre[i], r); 61 ans += max(0, R - L + 1); 62 } 63 } else { 64 for (int i = mid; i <= r; i++) { 65 int L = max(suf[i], l), R = min(mid, i - len + 1); 66 ans += max(0, R - L + 1); 67 } 68 } 69 query(l, mid - 1, ans); query(mid + 1, r, ans); 70 } 71 72 int main() { 73 int t; scanf("%d", &t); 74 while (t--) { 75 scanf("%d%d", &n, &k); 76 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 77 build(1, 1, n); 78 int pos = 0; 79 for (int i = 1; i <= n; i++) { // 计算从当前位置开始,向右延伸最远到什么位置,区间内的元素依然unique 80 while (pos < n && !vis[a[pos + 1]]) { // 不用set可以少一个log 81 pos++; 82 vis[a[pos]] = true; 83 } 84 pre[i] = pos; 85 vis[a[i]] = false; 86 } 87 pos = n + 1; 88 for (int i = n; i >= 1; i--) { 89 while (pos > 1 && !vis[a[pos - 1]]) { 90 pos--; 91 vis[a[pos]] = true; 92 } 93 suf[i] = pos; 94 vis[a[i]] = false; 95 } 96 ll ans = 0; 97 query(1, n, ans); 98 printf("%lld\n", ans); 99 } 100 return 0; 101 }