• Codeforces Round #285 (Div. 2) ABCD


    A题

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 
     7 using namespace std;
     8 
     9 #define LL long long
    10 #define eps 1e-8
    11 #define inf 0x3f3f3f3f
    12 #define mnx 100010
    13 
    14 int main(){
    15     int a, b, c, d;
    16     scanf( "%d%d%d%d", &a, &b, &c, &d );
    17     int a1 = max( 3 * a / 10, a - a / 250 * c );
    18     int a2 = max( 3 * b / 10, b - b / 250 * d );
    19     if( a1 > a2 ) puts( "Misha" );
    20     else if( a1 == a2 ) puts( "Tie" );
    21     else puts( "Vasya" );
    22     return 0;
    23 }
    View Code

    B题

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 
     7 using namespace std;
     8 
     9 #define LL long long
    10 #define eps 1e-8
    11 #define inf 0x3f3f3f3f
    12 #define mnx 1010
    13 
    14 char s[mnx][mnx], ch[mnx][mnx];
    15 int main(){
    16     int n, m = 0;
    17     scanf( "%d", &n );
    18     for( int i = 0; i < n; ++i ){
    19         cin >> s[m] >> ch[m];
    20         bool ok = 1;
    21         int j;
    22         for( j = 0; j < m; ++j ){
    23             if( strcmp( ch[j], s[m] ) == 0 ){ ok = 0; break; }
    24         }
    25         if( ok ) m++;
    26         else strcpy( ch[j], ch[m] );
    27     }
    28     cout << m << endl;
    29     for( int i = 0; i < m; ++i ){
    30         cout << s[i] << " " << ch[i] << endl;
    31     }
    32 }
    View Code

    C题 傻逼了,想错了。。后来发现把相连的边的数量当做入度,把全部node都塞进优先队列里,每次弹出度数最小的点u。如果访问过或者度数为0,就continue;否则就找到 v = u.val ^ x[u],给v所在节点的入度减1,x[v] ^= u,再把v塞进队列里,同时标记u已经访问过。记录边(u,v)我直接就用了vector

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <queue>
     7 #include <vector>
     8 
     9 using namespace std;
    10 
    11 #define LL long long
    12 #define eps 1e-8
    13 #define inf 0x3f3f3f3f
    14 #define mnx 300100
    15 
    16 vector<int> g[mnx];
    17 struct node{
    18     int in, val, id;
    19     bool operator < ( const node &b ) const {
    20         return in > b.in;
    21     }
    22 }c[mnx];
    23 int x[mnx];
    24 bool vis[mnx];
    25 int main(){
    26     int n, m = 0;
    27     scanf( "%d", &n );
    28     priority_queue<node> q;
    29     for( int i = 0; i < n; ++i ){
    30         scanf( "%d %d", &c[i].in, &c[i].val );
    31         c[i].id = i;
    32         q.push( c[i] );
    33     }
    34     while( !q.empty() ){
    35         node kk = q.top(); q.pop();
    36         int u = kk.id;
    37         if( vis[u] ) continue;
    38         vis[u] = 1;
    39         if( kk.in == 0 ) continue;
    40         int v = kk.val ^ x[u];
    41         x[v] ^= u;
    42         c[v].in--;
    43         q.push( c[v] );
    44         g[u].push_back( v );
    45         m++;
    46     }
    47     cout << m << endl;
    48     for( int i = 0; i < n; ++i ){
    49         int k = g[i].size();
    50         for( int j = 0; j < k; ++j )
    51             cout << i << " " << g[i][j] << endl;
    52     }
    53     return 0;
    54 }
    View Code

    D题 看到别人的题解说的 康托展开。果然知识面不够丰富。

    如我想知道321是{1,2,3}中第几个小的数可以这样考虑 :

    第一位是3,当第一位的数小于3时,那排列数小于321 如 123、 213 ,小于3的数有1、2 。所以有2*2!个。再看小于第二位2的:小于2的数只有一个就是1 ,所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个。所以321是第6个小的数。 2*2!+1*1!+0*0!就是康托展开。

    一个全排列 ,可以看成a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!, 那么其实只要处理出每一项的系数,然后把两个序列的系数加起来,然后进行进位操作,就可以求出答案的每一项的系数。求系数实际上就是求后面有多少个数是小于这个数的。这个过程要利用树状数组来维护。

    求出答案的系数后,再二分找答案(开始的时候一直都写不对这个二分,后来看了题解的二分,发现自己有智商捉急了)。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <queue>
     7 #include <vector>
     8 
     9 using namespace std;
    10 
    11 #define LL long long
    12 #define eps 1e-8
    13 #define inf 0x3f3f3f3f
    14 #define mnx 300100
    15 
    16 int p[mnx], q[mnx], bit[mnx], n;
    17 int sum( int x ){
    18     int ret = 0;
    19     while( x > 0 ){
    20         ret += bit[x];
    21         x -= x & -x;
    22     }
    23     return ret;
    24 }
    25 void add( int i, int x ){
    26     while( i <= n ){
    27         bit[i] += x;
    28         i += i & -i;
    29     }
    30 }
    31 int main(){
    32     scanf( "%d", &n );
    33     for( int i = 1; i <= n; ++i ){
    34         scanf( "%d", &p[i] );
    35         int tmp = sum( p[i] );
    36         q[i] += p[i] - tmp;
    37         add( p[i] + 1, 1 );
    38     }
    39     memset( bit, 0, sizeof( bit ) );
    40     for( int i = 1; i <= n; ++i ){
    41         scanf( "%d", &p[i] );
    42         int tmp = sum( p[i] );
    43         q[i] += p[i] - tmp;
    44         add( p[i] + 1, 1 );
    45     }
    46     for( int i = n; i > 0; --i )
    47         if( q[i] >= ( n - i + 1) ){
    48             q[i-1] += q[i] / ( n - i + 1 );
    49             q[i] %= ( n - i + 1);
    50         }
    51     memset( bit, 0, sizeof( bit ) );
    52     for( int i = 1; i <= n; ++i ) add( i, 1 );
    53     for( int i = 1; i <= n; ++i ){
    54         int l = 1, r = n;
    55         while( l < r ){
    56             int mid = ( l+r ) >> 1;        设q[i] = 2, mid = 4, 数字2已经用了。
    57             int tmp = sum( mid );          假设4还没有用,这时tmp = 3, tmp - 1 == 2 == q[i], 4应该是右端点
    58             if( tmp - 1 < q[i] )           假设4已经用了,这时tmp = 2, tmp - 1 == 1 < q[i], 此时5应该是左端点
    59                 l = mid + 1;
    60             else r = mid;
    61         }
    62         cout << l - 1 << " ";
    63         add( l, -1 );
    64     }
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    Tornado输出和响应头
    sqlalchemy 学习(二)scoped session
    04:sqlalchemy操作数据库 不错
    sqlalchemy(二)高级用法
    红黑树
    Minimum Window Substring
    Max Points on a Line
    分治算法
    Maximum Subarray
    Word Break
  • 原文地址:https://www.cnblogs.com/LJ-blog/p/4230015.html
Copyright © 2020-2023  润新知