One Bamboo Contest Round #12(Clone from 2020 ICPC Shenyang)

G. The Witchwood

签到

#include <bits/stdc++.h>
#define int long long
using namespace std;

int read(){
    int x = 0 , ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = x * 10 + ch - '0' , ch = getchar();
    return x;
}


int32_t main(){
    int n = read() , m = read();
    vector<int> a(n);
    for( auto & i : a ) i = read();
    std::sort(a.begin(), a.end(),greater<int>());
    int res = 0;
    for( int i = 0 ; i < m ; i ++ )
        res += a[i];
    cout << res << "\n";
    return 0;
}

F. Kobolds and Catacombs

题目的意思是,把序列尽可能的划分成多个子区间,要求对子区间排序后整个序列有序。

首先设第\(j\)个区间为\([l_j,r_j]\),由此可知\(l_1=1,l_j = r_{j-1}+1\),并且每个区间应该满足\([l_j,r_j]\)中的最大值小于\([r_j+1,n]\)中的最小值。

所以先计算出后缀最小值,然后根据后缀最小值就能找到每个右端点的位置。

#include <bits/stdc++.h>
#define int long long
using namespace std;

int read(){...}

int32_t main(){
    int n = read()  , cnt = 0;
    vector<int> v(n) , b(n);
    for( auto & i : v ) i = read();
    b[n-1] = v[n-1];
    for( int i = n - 2 ; i >= 0 ; i -- ) b[i] = min( v[i] , b[i+1] );
    b.push_back(INT_MAX) , v.push_back(INT_MIN) ;
    int l = 0;
    for( int i = 0 ; i < n && l < n ; i ++ ){
        if( v[i] > v[l] ) l = i;
        if( b[i+1] >= v[l] ) cnt ++ , l = i+1;
    }
    cout << cnt << "\n";
    return 0;
}

K. Scholomance Academy(补题)

这道题感觉蛮难理解的,最主要的就是那个AUC的积分,其实要求的就是就是样例解释里面阴影部分的面积。

因为数据是离散的,所以可以直接枚举排序后的\(a_i\)作为\(\theta\)的值,如果是阳性TP--,如果是阴性就要统计答案。

至于题目中定义的几个概念是机器学习中的东西,可以参考这篇博客

#include <bits/stdc++.h>
#define int long long
using namespace std;

struct Node{
    bool c;
    int s;
    Node( bool c = false , int s = 0 ) : c(c) , s(s){};
    bool operator < ( Node b ) const {
        if( s == b.s ){
            if(b.c) return false;
            if(c) return true;
        }
        return s < b.s;
    }
};


int32_t main(){
    int n , positive = 0 , negative = 0;
    cin >> n;
    vector<Node> a(n+1);
    for( int i = 1 ; i <= n ; i ++ ){
        char c;
        cin >> c >> a[i].s;
        a[i].c = (c == '+');
        if( a[i].c ) positive ++;
        else negative ++;
    }
    sort( a.begin()+1 , a.end());
    long double res = 0 , tp = positive , cnt = positive * negative;
    for( int i = 1 ; i <= n ; i ++ ){
        if( a[i].c ) tp --;
        else res += tp;
    }
    cout << fixed << setprecision(9) << res / cnt;
   return 0;
}

D. Journey to Un'Goro(补题)

\(p_i\)表示前\(i\)中有多少个\(r\),则题目要求对于区间\([l,r]\)满足\(p_r-p_{l-1}\)为奇数的区间尽可能的多。

那么则\(p_i\)为奇数的个数和为偶数的个数越接近越多,最多的情况就是各一半。注意的是\(i\)的取值是\([0,n]\)\(n+1\)个。

那么用搜索枚举出前100种情况就好,剪枝如果过程种\(p_i\)为奇数(或为偶数)的个数大于一半就一定不行

#include <bits/stdc++.h>
#define int long long
using namespace std;

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x * f;
}

vector<char> s;
int cnt = 0 , n , res , ans;

void dfs( int i , int cntEven , int cntOdd , int p ){
    if( cntEven > ans || cntOdd > ans ) return;
    if( i == n ){
        if( abs( cntOdd - cntEven) <= 1 ){
            for( auto c : s ) printf("%c",c);
            printf("\n");
            if( ++ cnt == 100 ) exit(0);
        }
        return;
    }
    s[i] = 'b';
    dfs( i+1 , cntEven + (p==0) , cntOdd + (p==1) , p );
    s[i] = 'r';
    dfs( i+1 , cntEven + (p==1) , cntOdd + (p==0) , p^1 );
    return;
}

int32_t main(){

    cin >> n;
    s = vector<char>(n);
    ans = (n+2) / 2 , res = ans * ( n+1-ans );
    cout << res << "\n";
    dfs( 0 , 1 , 0 , 0 );
    return 0;
}
posted @ 2023-01-08 15:06  PHarr  阅读(16)  评论(0编辑  收藏  举报