首页 > 代码库 > Codeforces Round #260 (Div. 2) ABCDE

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 long11 #define ull unsigned long long12 #define inf 0x3f3f3f3f13 #define eps 1e-814 #define MP make_pair15 #define lson l, m, rt << 116 #define rson m+1, r, rt << 1 | 117 #define mod 233333318 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 20000013 #define PI acos(-1.0)14 #define ll long long15 #define ull unsigned long long16 #define inf 0x3f3f3f3f17 #define eps 1e-818 #define MP make_pair19 #define lson l, m, rt << 120 #define rson m+1, r, rt << 1 | 121 #define mod 233333322 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