首页 > 代码库 > Codeforces Round #243

Codeforces Round #243

CF 243  DIV1 & DIV2

 

DIV2的A和B都太水,直接暴力搞就可以的。

DIV2A

 1 /* ***********************************************
 2 Author        :kuangbin
 3 Created Time  :2014/4/30 19:42:51
 4 File Name     :E:\2014ACM\Codeforces\CF243\DIV2_A.cpp
 5 ************************************************ */
 6 
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 
21 int a[110];
22 int main()
23 {
24     //freopen("in.txt","r",stdin);
25     //freopen("out.txt","w",stdout);
26     int n,s;
27     while(scanf("%d%d",&n,&s) == 2)
28     {
29         for(int i = 0;i < n;i++)
30             scanf("%d",&a[i]);
31         sort(a,a+n);
32         int ans = 0;
33         for(int i = 0;i < n-1;i++)
34             ans += a[i];
35         if(ans <= s)printf("YES\n");
36         else printf("NO\n");
37     }
38     return 0;
39 }
View Code

DIV2B

 1 /* ***********************************************
 2 Author        :kuangbin
 3 Created Time  :2014/4/30 19:53:16
 4 File Name     :E:\2014ACM\Codeforces\CF243\DIV2_B.cpp
 5 ************************************************ */
 6 
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 const int MAXN = 110;
21 int a[MAXN][MAXN];
22 int b[MAXN][MAXN];
23 
24 int main()
25 {
26     //freopen("in.txt","r",stdin);
27     //freopen("out.txt","w",stdout);
28     int n,m;
29     while(scanf("%d%d",&n,&m) == 2)
30     {
31         for(int i = 0;i < n;i++)
32             for(int j = 0;j < m;j++)
33                 scanf("%d",&a[i][j]);
34         int tmp = n;
35         if(tmp%2)
36         {
37             printf("%d\n",n);
38             continue;
39         }
40         for(int i = 0;i < n;i++)
41             for(int j = i+1;j < n;j++)
42             {
43                 int tt = 1;
44                 for(int k = 0;k < m;k++)
45                     if(a[i][k] != a[j][k])
46                     {
47                         tt = 0;
48                         break;
49                     }
50                 b[i][j] = b[j][i] = tt;
51             }
52         for(int t = 1;t <= n;t++)
53         {
54             int tmp = t;
55             while(tmp < n)tmp *= 2;
56             if(tmp != n)continue;
57             bool flag = true;
58             int mir = t;
59             while(mir != n)
60             {
61                 for(int i = 0;i < mir;i++)
62                     if(b[i][2*mir-1-i] == 0)
63                     {
64                         flag = false;
65                         break;
66                     }
67                 if(!flag)break;
68                 mir *= 2;
69             }
70             if(flag)
71             {
72                 printf("%d\n",t);
73                 break;
74             }
75         }
76     }
77     return 0;
78 }
View Code

 

DIV1A

题意:

给出了n(1<=n<=200)的数列a, 让你最多交换k(1<=k<=10)次,使得最大连续子序列的和最大。输出最大的连续子序列和。

 

因为n比较小,直接暴力枚举区间,然后将这个区间的k个小的,换成比较大的。

 

代码君:

 1 /* ***********************************************
 2 Author        :kuangbin
 3 Created Time  :2014/4/27 23:29:36
 4 File Name     :E:\2014ACM\Codeforces\CF243\A.cpp
 5 ************************************************ */
 6 
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 
21 const int MAXN = 220;
22 int a[MAXN];
23 int b[MAXN];
24 int c[MAXN];
25 int main()
26 {
27     //freopen("in.txt","r",stdin);
28     //freopen("out.txt","w",stdout);
29     int n,k;
30     while(scanf("%d%d",&n,&k) == 2)
31     {
32         for(int i = 1;i <= n;i++)
33             scanf("%d",&a[i]);
34         int ans = -1000000000;
35         for(int l = 1;l <= n;l++)
36             for(int r = l;r<= n;r++)
37             {
38                 int cnt1 = 0;
39                 int cnt2 = 0;
40                 for(int i = 1;i <= n;i++)
41                 {
42                     if(i >= l && i <= r)
43                         b[cnt1++] = a[i];
44                     else c[cnt2++] = a[i];
45                 }
46                 sort(b,b+cnt1);
47                 sort(c,c+cnt2);
48                 reverse(c,c+cnt2);
49                 int tt = min(cnt1,cnt2);
50                 tt = min(tt,k);
51                 for(int i = 1;i < cnt1;i++)
52                     b[i] += b[i-1];
53                 for(int i = 1;i < cnt2;i++)
54                     c[i] += c[i-1];
55                 
56 
57                 for(int i = 0;i <= tt;i++)
58                 {
59                     int num1 = i;
60                     int num2 = i;
61                     int tmp = b[cnt1-1];
62                     if(num1 > 0)tmp -= b[num1-1];
63                     if(num2 > 0)tmp += c[num2-1];
64                     ans = max(ans,tmp);
65                 }
66 
67             }
68         printf("%d\n",ans);
69     }
70     return 0;
71 }
View Code

 

DIV1B

给出一个n*m的01矩阵, 让你最多改变k个里面的值(0变1,1变0), 使得0、1的连通分量是矩阵。输出最少步数

1?≤?n,?m?≤?100; 1?≤?k?≤?10

 

题解:

如果01连通分量是矩形,

那么矩形一定是这样的:

0101010

1010101

0101010

1010101

(上面的01代表子矩阵块)。

也就是每一行要么是相同,要么是相反的。

 

如果n>k, 肯定有一行是不能改变的,那么枚举这一行,然后其余的要么变相同,要么变相反,看最少的步数。

如果n<k ,那么可以枚举第一列的状态(2^k), 然后其余列变成和第一列相同或者相反。

 

 1 /* ***********************************************
 2 Author        :kuangbin
 3 Created Time  :2014/4/29 11:30:04
 4 File Name     :E:\2014ACM\Codeforces\CF243\B.cpp
 5 ************************************************ */
 6 
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 const int MAXN = 110;
21 int a[MAXN][MAXN];
22 
23 int main()
24 {
25     //freopen("in.txt","r",stdin);
26     //freopen("out.txt","w",stdout);
27     int n,m,k;
28     while(scanf("%d%d%d",&n,&m,&k) == 3)
29     {
30         for(int i = 0;i < n;i++)
31             for(int j = 0;j < m;j++)
32                 scanf("%d",&a[i][j]);
33         int ans = 100000000;
34         if(n > k)
35         {
36             for(int t = 0;t < n;t++)
37             {
38                 int tmp = 0;
39                 for(int i = 0;i < n;i++)
40                 {
41                     int cnt = 0;
42                     for(int j = 0;j < m;j++)
43                         if(a[i][j] == a[t][j])
44                             cnt++;
45                     tmp += min(cnt,m-cnt);
46                 }
47                 ans = min(tmp,ans);
48             }
49         }
50         else
51         {
52             for(int t = 0;t < (1<<n);t++)
53             {
54                 int tmp = 0;
55                 for(int j = 0;j < m;j++)
56                 {
57                     int cnt = 0;
58                     for(int i = 0;i < n;i++)
59                         if(a[i][j] == ((t>>i)&1))
60                             cnt++;
61                     tmp += min(cnt,n-cnt);
62                 }
63                 ans = min(tmp,ans);
64             }
65         }
66         if(ans <= k)printf("%d\n",ans);
67         else printf("-1\n");
68     }
69     return 0;
70 }
View Code

 

DIV1C

题意:比较长,自己看题目吧

1?≤?s?≤?3·10^5; 10^3?≤?e?≤?10^4

所以第一个操作最多是300次.

用dp[i][j] 表示a序列消掉了前i个,消了j次,b序列的最小位置。

转移的时候,dp[i][j], 其实就是dp[0][j-1],dp[1][j-1],......dp[i-1][j-1]中最小的,下一个a[i]的位置。

用个数组标记下位置,因为那个最小值是递减的。

 1 /* ***********************************************
 2 Author        :kuangbin
 3 Created Time  :2014/4/29 22:16:58
 4 File Name     :E:\2014ACM\Codeforces\CF243\C.cpp
 5 ************************************************ */
 6 
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 
21 int dp[310][100010];
22 int a[100010];
23 int b[100010];
24 vector<int>vb[100010];
25 int next[100010];
26 
27 int main()
28 {
29     //freopen("in.txt","r",stdin);
30     //freopen("out.txt","w",stdout);
31     int n,m,s,e;
32     while(scanf("%d%d%d%d",&n,&m,&s,&e) == 4)
33     {
34         for(int i = 0;i < n;i++)
35             scanf("%d",&a[i]);
36         for(int i = 0;i < m;i++)
37             scanf("%d",&b[i]);
38         for(int i = 1; i <= 100000;i++)
39             vb[i].clear();
40         for(int i = 0;i < m;i++)
41             vb[b[i]].push_back(i);
42         for(int i = 1; i <= 100000;i++)
43             vb[i].push_back(m);
44         int k = s/e;
45         int ans = 0;
46         for(int i = 1;i <= k;i++)
47         {
48             for(int j = 1;j <= 100000;j++)
49                 next[j] = vb[j].size() - 1;
50             int mm = m;
51             if(i == 1)mm = -1;
52             for(int j = 0;j < n;j++)
53             {
54                 while(next[a[j]] > 0 && vb[a[j]][next[a[j]]-1] > mm)
55                     next[a[j]]--;
56                 dp[i][j] = vb[a[j]][next[a[j]]];
57                 if(i > 1)mm = min(mm,dp[i-1][j]);
58                 if(dp[i][j] < m && j + dp[i][j] + 2 + e*i <= s)
59                     ans = max(ans,i);
60             }
61         }
62         printf("%d\n",ans);
63     }
64     return 0;
65 }
View Code

 

DIV1D

题意,给了n个点, 让你求出有多少个平行于坐标轴的正方形,四个点都在给定的点上。

可以使用hash或者二分查找,快速判断一个点是不是存在。

枚举x坐标,如果x的个数<sqrt(n),  那么两重循环枚举这个x的点,确定边长,然后进行hash判断是不是存在。

如果x的个数>=sqrt(n), 那么枚举下所有的点,来确定下边长,然后进行hash判断

 

 1 /* ***********************************************
 2 Author        :kuangbin
 3 Created Time  :2014/4/30 18:27:57
 4 File Name     :E:\2014ACM\Codeforces\CF243\D.cpp
 5 ************************************************ */
 6 
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 
21 vector<int>vx[100010];
22 bool has(int x,int y)
23 {
24     if(x > 100000 || y > 100000 || x < 0 || y < 0)return false;
25     return binary_search(vx[x].begin(),vx[x].end(),y);
26 }
27 int main()
28 {
29     //freopen("in.txt","r",stdin);
30     //freopen("out.txt","w",stdout);
31     int n;
32     while(scanf("%d",&n) == 1)
33     {
34         for(int i = 0;i <= 100000;i++)
35             vx[i].clear();
36         int x,y;
37         for(int i = 0;i < n;i++)
38         {
39             scanf("%d%d",&x,&y);
40             vx[x].push_back(y);
41         }
42         for(int i = 0;i <= 100000;i++)
43             sort(vx[i].begin(),vx[i].end());
44         int ans = 0;
45         int bd = (int)sqrt(1.0*n);
46         for(int x = 0;x <= 100000;x++)
47             if(vx[x].size())
48             {
49                 if(vx[x].size() < bd)
50                 {
51                     for(int i = 0;i < vx[x].size();i++)
52                         for(int j = i+1;j < vx[x].size();j++)
53                         {
54                             int d = vx[x][j] - vx[x][i];
55                             if(has(x+d,vx[x][i]) && has(x+d,vx[x][j]))
56                                 ans++;
57                         }
58                 }
59                 else
60                 {
61                     for(int xx = x+1;xx <= 100000;xx++)
62                         for(int i = 0;i < vx[xx].size();i++)
63                         {
64                             int yy = vx[xx][i];
65                             int d = xx - x;
66                             if(has(x,yy) && has(x,yy+d) && has(xx,yy+d))
67                                 ans++;
68                         }
69                 }
70             }
71         printf("%d\n",ans);
72     }
73     return 0;
74 }
View Code

DIV1E

经典的DP题

 

 

使用dp[i][j] 表示最多j个不相交区间,最靠左的j个不相交区间的最后一个区间位置是i.

 

如果dp[i][j] -> dp[ii][j+1]的话,2^( (ii-i)*i ) 这种是横跨的区间,可选可不选。

(ii-i)个区间是最少要选择一个的,  2^(ii-i)-1

然后就可以得出来了。

 1 /* ***********************************************
 2 Author        :kuangbin
 3 Created Time  :2014/4/28 0:47:23
 4 File Name     :E:\2014ACM\Codeforces\CF243\E.cpp
 5 ************************************************ */
 6 
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 const int MOD = 1e9+7;
21 const int MAXN = 550;
22 int dp[MAXN][MAXN];//dp[i][j]表示有j个不相交区间,最左的最后一个区间的位置是i
23 void Add(int &a,int b)
24 {
25     a += b;
26     while(a >= MOD)a -= MOD;
27 }
28 int two[510*510];
29 int main()
30 {
31     //freopen("in.txt","r",stdin);
32     //freopen("out.txt","w",stdout);
33     int n,k;
34     two[0] = 1;
35     for(int i = 1;i <= 500*500;i++)
36         two[i] = 2*two[i-1]%MOD;
37     while(scanf("%d%d",&n,&k) == 2)
38     {
39         memset(dp,0,sizeof(dp));
40         dp[0][0] = 1;
41         for(int i = 0;i < n;i++)
42             for(int j = 0;j < k;j++)
43                 if(dp[i][j])
44                 {
45                     for(int ii = i+1;ii <= n;ii++)
46                     {
47                         long long tmp = two[i*(ii - i)];
48                         tmp = tmp*(two[ii-i]-1)%MOD;
49                         Add(dp[ii][j+1],tmp*dp[i][j]%MOD);
50                     }
51                 }
52         int ans = 0;
53         for(int i = 0;i <= n;i++)
54             Add(ans,(long long)dp[i][k]*two[i*(n-i)]%MOD);
55         printf("%d\n",ans);
56     }
57     return 0;
58 }
View Code