Codeforces Round #260 (Div. 2) ABCDE

A题逗比了,没有看到All ai are distinct. All bi are distinct. 其实很水的。。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define mnx 100002
 8 
 9 
10 struct latop{
11     int p, q;
12     bool operator < ( const latop & b ) const {
13         return p < b.p;
14     }
15 }a[mnx];
16 int main(){
17     int n;
18     scanf( "%d", &n );
19     for( int i = 0; i < n; i++ ){
20         scanf( "%d %d", &a[i].p, &a[i].q );
21     }
22     sort( a, a + n );
23     bool flag = 0;
24     for( int i = 1; i < n; i++ ){
25         if( a[i].q < a[i-1].q ) flag = 1;
26     }
27     if( flag ) puts( "Happy Alex" );
28     else puts( "Poor Alex" );
29     return 0;
30 }
View Code

B题找循环节。。循环节是4,然后输入再长的数,也只需要看最后两位,因为100的倍数肯定能够整除4,就看最后两位。。结果又逗比了,数组开小了,最后re了。。太粗心了。。

 1 #include<string>
 2 #include<cmath>
 3 #include<map>
 4 #include<queue>
 5 
 6 using namespace std;
 7 
 8 #define mnx 1000000
 9 #define PI acos(-1.0)
10 #define ll long long
11 #define ull unsigned long long
12 #define inf 0x3f3f3f3f
13 #define eps 1e-8
14 #define MP make_pair
15 #define lson l, m, rt << 1
16 #define rson m+1, r, rt << 1 | 1
17 #define mod 2333333
18 
19 int a[4] = { 4, 0, 0, 0 };
20 char ch[mnx];
21 int main(){
22     scanf( "%s", &ch );
23     int n = strlen( ch );
24     int k = 0;
25     if( n <= 2 ){
26         for( int i = 0; i < n; i++ ){
27             k = k * 10 + ch[i] - '0';
28         }
29     //  cout<<k<<endl;
30         k %= 4;
31         printf( "%d\n", a[k] );
32     }
33     else{
34         for( int i = n-2; i < n; i++ ){
35             k = k * 10 + ch[i] - '0';
36         }
37     //  cout<<k<<endl;
38         k %= 4;
39         printf( "%d\n", a[k] );
40     }
41     return 0;
42 }
View Code

C题先排序,然后把相同的弄掉,if( b[i] == b[i-1] + 1 )  dp[i] = max( dp[i-2] + sum[i], dp[i-1] ),要么就是选当前这个b[i],然后dp[i]的值就是dp[i-2] + sum[i],要么就选b[i-1],然后dp[i]的值就是dp[i-1];else dp[i] = dp[i] = dp[i-1] + sum[i]; 最后答案就是 dp[cnt]; 具体看代码。。当时写的比较稳妥,多写了一些。。结果还是因为longlong跪了几发,这是后来写的代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<string>
 6 #include<cmath>
 7 #include<map>
 8 #include<queue>
 9 
10 using namespace std;
11 
12 #define mnx 200000
13 #define PI acos(-1.0)
14 #define ll long long
15 #define ull unsigned long long
16 #define inf 0x3f3f3f3f
17 #define eps 1e-8
18 #define MP make_pair
19 #define lson l, m, rt << 1
20 #define rson m+1, r, rt << 1 | 1
21 #define mod 2333333
22 
23 ll a[mnx], b[mnx], sum[mnx], dp[mnx];
24 int main(){
25     int n;
26     scanf( "%d", &n );
27     for( int i = 1; i <= n; i++ ){
28         scanf( "%I64d", &a[i] );
29     }
30     sort( a + 1, a + 1 + n );
31     int cnt = 0;
32     for( int i = 1; i <= n; i++ ){
33         if( a[i] != b[cnt] ){
34             ++cnt;
35             b[cnt] = a[i];
36             sum[cnt] = a[i];
37         }
38         else sum[cnt] += a[i];
39     }
40     dp[1] = sum[1]; 
41     for( int i = 2; i <= cnt; i++ ){
42         if( b[i] == b[i-1] + 1 ){
43             dp[i] = max( dp[i-2] + sum[i], dp[i-1] );
44         }
45         else{
46             dp[i] = dp[i-1] + sum[i];
47         } 
48     }
49     cout<<dp[cnt]<<endl;
50     return 0;
51 }
View Code

D题trie树,不会做。。赛后问了思路,弄了很久才明白。。原本的想法是 trie的根就是必败,然后dfs,第一层就是必胜,遍历到叶子节点,看叶子节点是必败还是必胜,如果叶子节点全是必胜的,说明先手的每次必胜,如果叶子节点全是必败的,说明先手的每次必败,如果叶子节点既有必胜又有必败的,说明先手的每次既能必胜也能必败。。后来发现这样想是错的,如果是abcs,abcab,先手走到c,接下来先手的输赢全部是由后手决定,后手走s,先手输,后手走a,先手赢。。这道题输赢的状态必须由叶子节点开始向根的方向推,看了超哥的代码,开两个bool数组,win[], can[],win数组表示下一步先手开始走,能不能赢,can数组表示下一步先手开始走,能不能输。。所以叶子节点就是win[u] = 0(先手下一步不能走,就不能赢),can[u] = 1(先手下一步不能走,肯定输)。。当一个节点有多个子节点,win[u] = 1就看 win[son[u][i]]里面有没有为0的,否则就是0;can[u] = 1就看can[son[u][i]]里面有没有为0的,否则就是0。。推到根节点的状态。。这样讲有点抽象,可以手动模拟一下 abcs, abcab这种情况。。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define mnx 100002
 8 
 9 int son[mnx][26], tot;
10 bool win[mnx], can[mnx];
11 void insert(char *s) {
12     int t = 0;
13     for (int i = 0; s[i]; ++i) {
14         int c = s[i] - 'a';
15         if (!son[t][c]) son[t][c] = ++tot;
16         t = son[t][c];
17     }
18 }
19 void dfs( int u ){
20     win[u] = 0, can[u] = 1;
21     bool hav = 0;
22     for( int i = 0; i < 26; i++ ){
23         if( son[u][i] ){
24             dfs( son[u][i] ); hav = 1;
25         }
26     }
27     if( !hav ) return ;
28     can[u] = 0;
29     for( int i = 0; i < 26; i++ ){
30         if( son[u][i] && !win[son[u][i]] ) win[u] = 1;
31         if( son[u][i] && !can[son[u][i]] ) can[u] = 1;
32     }
33 }
34 char ch[mnx];
35 int main(){
36     int n, k;
37     scanf( "%d%d", &n, &k );
38     for( int i = 0; i < n; i++ ){
39         scanf( "%s", ch );
40         insert( ch );
41     }
42     dfs( 0 );
43     if( win[0] == false ) puts( "Second" );
44     else{
45         if( can[0] == true ) puts( "First" );
46         else puts( (k & 1) ? "First" : "Second" );
47     }
48     return 0;
49 }
View Code

E题没时间看,赛后看了一下,发现也不是很难,树的直径和并查集。。比较难处理的就是connect them by a road so as to minimize the length of the longest path in the resulting region  使联通后的区域的直径最小,那么就应该从两条直径的中间点连一条边,使他们联通。。假设要联通两个区域为u,v,直径为val[u], val[v],则联通后的直径应该是 max( val[u], val[v], 1 + ( val[u] - val[u] / 2 ) + ( val[v] - val[v] / 2 );

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define mnx 600005
 8 #define inf 0x3f3f3f3f
 9 
10 int dis[2][mnx],  fa[mnx], val[mnx];
11 int vv[mnx], first[mnx], nxt[mnx], e;
12 bool vis[mnx], in[mnx];
13 int n, m, query, tot;
14 void init(){
15     memset( first, -1, sizeof(first) );
16     memset( dis, 0x3f, sizeof(dis) );
17     e = 0;
18 }
19 void add( int u, int v ){
20     vv[e] = v, nxt[e] = first[u], first[u] = e++;
21 }
22 int q[mnx];
23 int bfs( int s, int *dis ){
24     int head = 0, tail = 0;
25     q[tail++] = s, dis[s] = 0;
26     while( head < tail ){
27         int u = q[head++];
28         vis[u] = 1;
29         for( int i = first[u]; i != -1; i = nxt[i] ){
30             int v = vv[i];
31             if( dis[v] > dis[u] + 1 ){
32                 dis[v] = dis[u] + 1;
33                 q[tail++] = v;
34             } 
35         }
36     }
37     int id = s, d = dis[s];
38     for( int i = 0; i < tail; i++ ){
39         if( dis[q[i]] > d ){
40             d = dis[q[i]], id = q[i];
41         }
42     }
43     return id;
44 }
45 int find( int s ){
46     if( s != fa[s] ){
47         fa[s] = find( fa[s] );
48     }
49     return fa[s];
50 }
51 void treeD( int s ){
52     int v = bfs( s, dis[0] );
53     int u = bfs( v, dis[1] );
54     val[find(u)] = dis[1][u];
55 }
56 int main(){
57     scanf( "%d %d %d", &n, &m, &query );
58     tot = n;
59     init();
60     for( int i = 0; i <= n + query; i++ ){
61         fa[i] = i;
62     }
63     while( m-- ){
64         int u, v;
65         scanf( "%d %d", &u, &v );
66         add( u, v ), add( v, u );
67         int fu = find( u ), fv = find( v );
68         fa[fu] = fv;
69     }
70     for( int i = 1; i <= n; i++ ){
71         if( !vis[i] ){
72             treeD( i );
73         }
74     }
75     while( query-- ){
76         int tye, u, v;
77         scanf( "%d", &tye );
78         if( tye == 1 ){
79             scanf( "%d", &u );
80             printf( "%d\n", val[find(u)] );
81         }
82         else{
83             scanf( "%d%d", &u, &v );
84             int fu = find( u ), fv = find( v );
85             if( fu == fv ) continue;
86             ++tot;
87             fa[fu] = fa[fv] = tot;
88             val[tot] = 1 + ( val[fu] - val[fu] / 2 ) + ( val[fv] - val[fv] / 2 );
89             val[tot] = max( val[tot], val[fu] );
90             val[tot] = max( val[tot], val[fv] );
91         }
92     }
93     return 0;
94 }
View Code

 

posted @ 2014-08-11 15:03  L__J  阅读(693)  评论(0编辑  收藏  举报