17国庆day2

2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) 

 题解:链接

Tournament Wins

 Gym - 101201K 

题意: 2^k个人,你排名第r, 问你能赢的期望次数.

至少赢 i 次的概率是 C(2^i-1, 2^k-r) / C(2^i-1, 2^k-1) ,化简一下

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int k, r;
 4 
 5 int main() {
 6         scanf("%d %d", &k, &r);
 7         int m = (1<<k) - r;
 8         double ans = 0;
 9         int i;
10         for(i = 1; (1<<i)-1 <= m; i++){
11             double p = 1.0;
12            // int a = (1<<k) - (1<<i) + 2 - r;
13             //int c = (1<<k) - r + 1;
14             int a = (1<<k) - 1;
15             int c = (1<<k) - r;
16             for(int j = 0; j <(1<<i)-1 ; j++) {
17                 p = p*c/a;
18                 a--;
19                 c--;
20             }
21             ans += p;
22         }
23         printf("%.5lf
", ans);
24 }
View Code

Maximum Islands

 Gym - 101201G 

题意: 给一个卫星图, 有陆地, 海洋和未知区域, 问最多有多少个陆地四连块.

首先明确已知的陆地周围必须都是海洋, 然后未知区域单独为陆地的情况下四连块才会最多.

黑白染色,求二分图最大独立集.

又是二分图匹配....感觉自己好菜哇=_=

 1 #include <bits/stdc++.h>
 2 #define CLR(m, a) memset(m, a, sizeof(m))
 3 using namespace std;
 4 const int maxn = 1610;
 5 
 6 struct Edge{
 7     int v, nex;
 8     Edge(int v=0, int nex=0) : v(v), nex(nex) {}
 9 }e[maxn<<2];
10 int head[maxn];
11 int cnt;
12 
13 void init(){
14     CLR(head,-1);
15     cnt = 0;
16 }
17 void add(int u, int v) {
18     e[cnt] = Edge(v, head[u]) ;
19     head[u] = cnt++ ;
20 }
21 
22 char p[42][42];
23 int vis[42][42];
24 
25 int n, m;
26 int dir[4][2] = {0,1,0,-1,1,0,-1,0};
27 void dfs(int x, int y){
28     vis[x][y] = 1;
29     for(int i = 0; i < 4; i++){
30         int dx = x + dir[i][0];
31         int dy = y + dir[i][1];
32         if(dx>=0&&dx<n&&dy>=0&&dy<m&&!vis[dx][dy]) {
33             if(p[dx][dy] == 'L') dfs(dx,dy);
34             if(p[dx][dy] == 'C') p[dx][dy] = 'W';
35         }
36     }
37 }
38 
39 int vb[maxn], vg[maxn], mcb[maxn];
40 
41 int Hungary(int u){
42     vg[u] = 1;
43     for(int i = head[u]; ~i; i = e[i].nex){
44         int v = e[i].v;
45         if(!vb[v]){
46             vb[v] = 1;
47             if(mcb[v] == -1 || Hungary(mcb[v])) {
48                 mcb[v] = u;
49                 return 1; 
50             }
51         }
52     }
53     return 0;
54 }
55 
56 int main(){
57   //  freopen("in.txt", "r", stdin);
58     while(scanf("%d %d", &n, &m)!= EOF) {
59         init();
60         for(int i = 0; i < n; i++) scanf("%s", p[i]);
61         int tot = 0;
62         CLR(vis, 0);
63         for(int i = 0; i < n; i++){
64             for(int j = 0; j < m; j++){
65                 if(p[i][j] == 'L'&& !vis[i][j]) {
66                     dfs(i,j);
67                     tot++;
68                 }
69             }
70         }
71         CLR(vis, 0);
72         int N = 0;
73         for(int i = 0; i < n; i++) 
74             for(int  j = 0; j < m; j++) 
75                 if(p[i][j]=='C') vis[i][j] = ++N;
76 
77         for(int i = 0; i < n; i++) {
78             for(int j = 0; j < m; j++) {
79                 if((i+j)%2==0 && vis[i][j]) {
80                     for(int k = 0; k < 4; k++) {
81                         int dx = i+dir[k][0];
82                         int dy = j+dir[k][1];
83                         if(dx>=0 && dx<n && dy>=0 && dy<m && vis[dx][dy]) add(vis[i][j], vis[dx][dy]); 
84                     }
85                 }
86             }
87         }
88         int ans = 0;
89         CLR(mcb, -1);
90         for(int i = 0; i < n; i++)
91             for(int j  = 0; j < m; j++)
92                 if(vis[i][j] && (i+j)%2 == 0) {
93                     CLR(vg, 0);
94                     CLR(vb, 0);
95                     if(Hungary(vis[i][j])) ans++;
96                 }
97         printf("%d
", N - ans + tot);
98     }
99 }
View Code

Alphabet

 Gym - 101201A 

求最长上升子序列.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 55;
 4 char s[maxn];
 5 int d[maxn];
 6 int main() {
 7     //freopen("in.txt", "r", stdin);
 8     while(scanf("%s", s) != EOF) {
 9         int n = strlen(s);
10         int ans = 0;
11         memset(d, 0, sizeof(d));
12         for(int i = 0; i < n; i++) {
13             for(int j = 0; j < i; j++) {
14                 if(s[j] < s[i]) d[i] = max(d[i], d[j]+1);
15                 ans = max(ans, d[i]);
16             }
17         }
18         printf("%d
", 25 - ans);
19     }
20 }
View Code

Cameras

 Gym - 101201C 

暴力也能过,有点慢900+ms

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 100010;
 5 
 6 int vis[maxn];
 7 int n, k, r;
 8 
 9 int main(){
10  //   freopen("in.txt", "r", stdin);
11     while(scanf("%d %d %d", &n, &k, &r) != EOF) {
12         memset(vis, 0, sizeof(vis));
13         for(int i = 0; i < k; i++) {
14             int x;
15             scanf("%d", &x);
16             vis[x] = 1;
17         }
18         int res = 0;
19         for(int i = 1; i+r-1 <= n; i++) {
20             int cnt = 0;
21             for(int j = i; j <= r+i-1; j++){
22                 if(vis[j]) cnt++;
23                 if(cnt==2) break;
24             }
25             int id = r+i-1;
26             while(cnt<2) {
27                 while(vis[id]) id--;
28                 vis[id] = 1;
29                 cnt++;
30                 res++;
31              //   printf("---%d
", id);
32             }
33         }
34         printf("%d
", res);
35     }
36 }
View Code

其实可以用树状数组维护下区间和~ 30ms

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 100010;
 5 
 6 int c[maxn], vis[maxn];
 7 int n, k, r;
 8 
 9 int lowbit(int x) {
10     return x&(-x);
11 }
12 void add(int x, int d){
13     while(x <= n) {
14         c[x] += d;
15         x += lowbit(x);
16     }
17 }
18 
19 int sum(int x) {
20     int ans = 0;
21     while(x > 0) {
22         ans += c[x];
23         x -= lowbit(x);
24     }
25     return ans;
26 }
27 
28 int main(){
29     //freopen("in.txt", "r", stdin);
30     while(scanf("%d %d %d", &n, &k, &r) != EOF) {
31         memset(c, 0, sizeof(c));
32         memset(vis, 0, sizeof(vis));
33         for(int i = 0; i < k; i++) {
34             int x;
35             scanf("%d", &x);
36             vis[x] = 1;
37             add(x, 1);
38         }
39         int res = 0;
40         for(int i = 1; i+r-1 <= n; i++) {
41             int cnt = sum(r+i-1) - sum(i-1);
42             int id = r+i-1;
43             while(cnt<2) {
44                 while(vis[id]) id--;
45                 add(id, 1);
46                 vis[id] = 1;
47                 cnt++;
48                 res++;
49             }
50         }
51         printf("%d
", res);
52     }
53 }
View Code

Shopping

 Gym - 101201J 

 题意:n件商品,k个人,每个人m元钱,从L走到R,每遇到一件商品就尽可能的多买,问最后剩余多少钱~

二分查找当前区间内小于m的最前位置

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long 
 4 
 5 const int maxn = 200010;
 6 
 7 ll a[maxn];
 8 ll dp[maxn][30];
 9 
10 void rmq_init(int n) {
11     for(int i = 1; i <= n; i++) dp[i][0] = a[i];
12     int k = 0;
13     while(1<<(k+1) <= n+1) k++;
14     for(int i = 1; i <= k; i++) {
15         for(int j = 0; j + (1<<i) -1 <= n; j++) {
16             dp[j][i] = min(dp[j][i-1], dp[j+(1<<i-1)][i-1]);
17         }
18     }
19 }
20 
21 ll rmq(int L, int R) {
22     int k = 0;
23     while(1<<(k+1) <= R-L+1) k++;
24     return min(dp[L][k], dp[R-(1<<k)+1][k]);
25 }
26 
27 int main(){
28     int n, k;
29     //freopen("in.txt", "r", stdin);
30     scanf("%d %d", &n, &k) ;
31         for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
32         rmq_init(n);
33         while(k--) {
34             ll m;
35             int p, q;
36             scanf("%lld %d %d", &m, &p, &q);
37             while(1){
38                 int L = p, R = q;
39                 while(L <= R) {
40                     int M = (L + R) >> 1;
41                     if(rmq(L,M) <= m) R = M-1;
42                     else L = M+1;
43               //      cout<<L<<"   "<<R<<endl;
44                 }
45                 if(L > q) {
46                     printf("%lld
", m);
47                     break;
48                 }
49             //  printf("%d %lld---
", L, a[L]);
50                 p = L+1;
51                 m %= a[L];
52                 if(m==0) {
53                     printf("%lld
", m);
54                     break;
55                 }
56             }
57         }
58     
59     return 0;
60 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7624266.html