codeforces #297 div2(only)

2015-03-28 01:34:38

总结:这场用来练java了... 

  赛中搞了A,B,C,然后开始坑E题... 暴力DFS结果TLE了... rank 300+(unofficial)

  赛后用c++补了D、E...(因为发现java的JSTL有点烦...)

A:模拟题,从左到右扫一遍,维护一个计数数组即可。

 1 import java.util.Scanner;
 2 
 3 public class Main{
 4     public static void main(String[] args){
 5         Scanner in = new Scanner(System.in);
 6         int n = in.nextInt();
 7         String str = in.next();
 8         char[] s = new char[str.length()];
 9         s = str.toCharArray();
10         int[] cnt = new int[30];
11         int sum = 0;
12         for(int i = 0; i < str.length(); ++i){
13             if(s[i] >= 'a' && s[i] <= 'z'){
14                 cnt[(int)(s[i] - 'a')]++;
15             }
16             else{
17                 int id = (int)(s[i] - 'A');
18                 if(cnt[id] == 0) sum++;
19                 else cnt[id]--;
20             }
21         }
22         System.out.println(sum);
23         in.close();
24     }
25 
26 }
View Code

 

B:经典的区间翻转,首先开一个cnt[]数组来计数,对于每一个操作[l,r],我们给cnt[l]++,最后才从1~n扫一遍,不断累加cnt[]

   如果累加值为奇数那么该数与对称位置的数交换,否则不交换。

 1 import java.util.Scanner;
 2 
 3 public class Main{
 4     public static void main(String[] args){
 5         Scanner in = new Scanner(System.in);
 6         char[] s = new char[200010];
 7         String str = in.next();
 8         s = str.toCharArray();
 9         int a,m = in.nextInt();
10         int[] v = new int[100010];
11         for(int i = 0; i < m; ++i){
12             a = in.nextInt();
13             v[a - 1] += 1;
14         }
15         int cur = 0;
16         for(int i = 0; i < str.length() / 2; ++i){
17             cur += v[i];
18             if(cur % 2 == 1){
19                 char tmp = s[i];
20                 s[i] = s[str.length() - 1 - i];
21                 s[str.length() - 1 - i] = tmp;
22             }
23         }
24         System.out.println(s);
25         in.close();
26     }
27 
28 }
View Code

 

C:排序之后从最大的stick开始贪心扫描即可。

 1 import java.util.*;
 2 
 3 public class Main{
 4     public static void main(String[] args){
 5         Scanner in = new Scanner(System.in);
 6         int n = in.nextInt();
 7         int[] l = new int[n];
 8         for(int i = 0; i < n; ++i) l[i] = in.nextInt();
 9         Arrays.sort(l);
10         int[] v = new int[2];
11         int sz = 0;
12         long ans = 0;
13         for(int i = n - 1; i >= 1; --i){
14             if(l[i]==l[i-1]){
15                 v[sz++] = l[i];
16                 --i;
17             }
18             else if(l[i]==l[i-1]+1){
19                 v[sz++] = l[i - 1];
20                 --i; 
21             }
22             if(sz >= 2){
23                 ans += (long)v[0] * (long)v[1];
24                 sz = 0;
25             }
26         }
27         System.out.println(ans);
28         in.close();
29     }
30 
31 }
View Code

 

D:神奇的规律... 只要一个2*2的矩阵里面有3个“.”,1个“*”,那么这个“*”就要变成“.”。那么我们一开始把所有“*”放入队列,然后检查其周围是否满足前述

   条件,然后如果当前“*”要变成“.”,就把其周围的所有“*”加入队列。(因为当前的"*"变成".",可能会导致其周围的"*"符合条件)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
18 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
19 #define MP(a,b) make_pair(a,b)
20 #define X first
21 #define Y second
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int n,m;
28 char g[2010][2010];
29 queue<pii > Q;
30 bool inq[2010][2010];
31 int dir[4][3][2] = {{{-1,-1},{-1,0},{0,-1}},{{-1,0},{-1,1},{0,1}},
32     {{0,-1},{1,-1},{1,0}},{{0,1},{1,0},{1,1}}};
33 
34 int main(){
35     scanf("%d%d",&n,&m);
36     REP(i,n) scanf("%s",g[i]);
37     REP(i,n) REP(j,m) if(g[i][j] == '*'){
38         Q.push(MP(i,j));
39          inq[i][j] = 1;
40     }
41     while(!Q.empty()){
42         pii cur = Q.front(); Q.pop();
43         inq[cur.X][cur.Y] = 0;
44         bool flag = false;
45         REP(o,4){
46             int cnt = 0;
47             REP(k,3){
48                 int tx = cur.X + dir[o][k][0];
49                 int ty = cur.Y + dir[o][k][1];
50                 if(tx < 0 || tx >= n || ty < 0 || ty >= m
51                         || g[tx][ty] == '*') break;
52                 cnt++;
53             }
54             if(cnt == 3){
55                 flag = true;
56                 break;
57             }
58         }
59         if(flag){
60             g[cur.X][cur.Y] = '.';
61             REP(o,4) REP(k,3){
62                 int tx = cur.X + dir[o][k][0];
63                 int ty = cur.Y + dir[o][k][1];
64                 if(tx < 0 || tx >= n || ty < 0 || ty >= m || g[tx][ty] == '.')
65                     continue;
66                 if(inq[tx][ty] == 0){
67                     inq[tx][ty] = 1;
68                     Q.push(MP(tx,ty));
69                 }
70             }
71         }
72     }
73     REP(i,n){
74         REP(j,m) printf("%c",g[i][j]);
75         puts("");
76     }
77     return 0;
78 }
View Code

 

E:一开始暴力... 果断T了。后来才知道是折半枚举,其实也明显,n<=25,直接枚举是3^25,如果折半就是3^12 , 3^13。

   所以我们将n分成两部分,分别暴力DFS搜索,用两个map数组来记录两部分得到的“和”,及其数量。

  (比如mp1[i][j]表示前半部分,有i个cube被贴上“!”标签得到的和为j的数量)

  分别搜素得到两个map数组后,我们可以枚举前半部分贴了i = 0~k个“!”标签,再枚举后半部分贴了0 <= j <= i 个“!”标签:

  那么问题就变成遍历mp1[i]的所有元素element,在mp2[j]中找S - element。

  所以,在过程中累加答案即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
18 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
19 #define MP(a,b) make_pair(a,b)
20 
21 typedef long long ll;
22 typedef pair<int,int> pii;
23 const int INF = (1 << 30) - 1;
24 
25 int n,k,top;
26 ll S,a[30],af[30];
27 map<ll,int> mp1[30],mp2[30];
28 
29 void Dfs1(int p,int num,ll sum){
30     if(p >= top){
31         mp1[num][sum]++;
32         return;
33     }
34     Dfs1(p + 1,num,sum);
35     if(sum + a[p] <= S) Dfs1(p + 1,num,sum + a[p]);
36     if(a[p] <= 18 && num < k && sum + af[p] <= S)
37         Dfs1(p + 1,num + 1,sum + af[p]);
38 }
39 
40 void Dfs2(int p,int num,ll sum){
41     if(p >= n){
42         mp2[num][sum]++;
43         return;
44     }
45     Dfs2(p + 1,num,sum);
46     if(sum + a[p] <= S) Dfs2(p + 1,num,sum + a[p]);
47     if(a[p] <= 18 && num < k && sum + af[p] <= S)
48         Dfs2(p + 1,num + 1,sum + af[p]);
49 }
50 
51 int main(){
52     scanf("%d%d%I64d",&n,&k,&S);
53     REP(i,n){
54         scanf("%I64d",&a[i]);
55         if(a[i] <= 18){
56             af[i] = 1;
57             for(int j = 2; j <= a[i]; ++j) af[i] *= (ll)j;
58         }
59     }
60     top = n / 2;
61     Dfs1(0,0,0);
62     Dfs2(top,0,0);
63     map<ll,int>::iterator it1,it2;
64     ll ans = 0;
65     for(int i = 0; i <= k; ++i){
66         for(it1 = mp1[i].begin(); it1 != mp1[i].end(); it1++){
67             for(int j = 0; j <= k - i; ++j)
68                 ans += (*it1).second * mp2[j][S - (*it1).first];
69         }
70     }
71     printf("%I64d\n",ans);
72     return 0;
73 }
View Code

 

posted @ 2015-03-28 01:55  Naturain  阅读(141)  评论(0编辑  收藏  举报