Codeforces Round #243

CF 243  DIV1 & DIV2

 

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

DIV2A

Codeforces Round #243
 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

Codeforces Round #243
 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个小的,换成比较大的。

 

代码君:

Codeforces Round #243
 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), 然后其余列变成和第一列相同或者相反。

 

Codeforces Round #243
 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]的位置。

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

Codeforces Round #243
 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判断

 

Codeforces Round #243
 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

然后就可以得出来了。

Codeforces Round #243
 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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(codeforces)