AtCoder Beginner Contest 247

A - Move Right

给一个四位的二进制,输出右移一位的结果

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

int n;
string s ;

int main()
{
    cin >> s;
    cout << '0';
    for( int i = 0 ; i <= 2 ; i ++ )
        cout << s[i];
}

B - Unique Nicknames

每一个人都有一个姓和一个名,要给每个人取一个昵称

昵称要满足两个条件,首先昵称必修与姓或名相同,其次昵称不能与其他人的姓或名相同

实际上把所有的所有的名和姓塞入到一个 map 中,只要一个人的名或姓是唯一的那么他就是可以起一个昵称

注意的是,会有人的名和姓相同

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

int n;
map<string , int> st;
string a[105] , b[105];

int main()
{
    cin >> n;
    for( int i = 1 ; i <= n ; i ++ ) {
        cin >> a[i] >> b[i];
        st[a[i]] ++ ;
        if( a[i] != b[i] ) st[b[i]] ++;
    }
    for( int i = 1 ; i <= n ; i ++ )
    {
        if( st[a[i]] == 1 || st[b[i]] == 1) continue;
        printf("No\n");
        return 0;
    }
    printf("Yes\n");
    return 0;
}

C - 1 2 1 3 1 2 1

题目给定了一个构造字符串的方法,\(s_i=s_{i-1}is_{i-1}\)

因为 n 很小直接构造就好

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

int n;
string s[20];

int main()
{
    cin >> n;
    s[1] = "1";
    for( int i = 2 ; i <= n ; i ++ )
        s[i] = s[i-1] + " " + to_string(i) + " " + s[i-1];
    cout << s[n];
    return 0;
}

D - Cylinder

首先给一个队列,然后有两种操作

  1. 插入 c 个 x
  2. 取出 c 个数并求和

如果单纯的模拟的话会 t,所以队列中存的是一个pair表示数和数的个数

然后每次我们取出一个pair如果有剩余的数就插回到队头,所以这里要用到双端队列

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

ll n , cnt;
deque< pair<ll,ll> > dq;

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;
}

int main() {
    n = read();
    for( ll op , m , x , c ; n ; n -- ) {
        op = read();
        if (op == 1)
            x = read(), c = read(), dq.push_back({x, c});
        else {
            m = read(), cnt = 0;
            while (m) {
                x = dq.front().first, c = dq.front().second, dq.pop_front();
                if (c <= m)
                    cnt += x * c, m -= c;
                else
                    cnt += x * m , dq.push_front({x, c - m}) , m = 0;
            }
            printf("%lld\n", cnt);
        }
    }
    return 0;
}

E - Max Min

给定长度为 n 的序列,问有多少个区间的最大值最小值是 x 和 y

首先枚举一下左端点,然后二分出符合条件的最小值和最大值即可

那么如何判区间时候符合条件呢?实际上就是用线段树来维护一下区间最值就好了

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

const int N = 2e5+5;
int n , maxx , miny , a[N] ;
ll cnt ;

struct Node{
    int l , r , maxval , minval;
    Node *left , *right;
    Node( int l , int r , int maxval , int minval , Node * left , Node * right ) : l(l) , r(r) , maxval(maxval) , minval(minval) , left(left) , right(right){};
} *root;

Node * build( int l , int r )
{
    if( l == r ) return new Node( l , r , a[l] , a[l] , 0 , 0 );
    int mid = ( l + r ) >> 1;
    Node * left = build( l , mid ) , * right = build( mid + 1 , r );
    return new Node( l , r , max( left -> maxval , right -> maxval) , min( left -> minval , right -> minval ) , left , right );
}

void query( int l , int r , Node * cur , int &maxval , int &minval )
{
    if( l == cur -> l && r == cur ->r )
    {
        maxval = max( maxval , cur -> maxval ) , minval = min( minval , cur -> minval );
        return ;
    }
    int mid = ( cur -> l + cur -> r ) >> 1;
    if( l > mid ) query( l , r , cur -> right , maxval , minval );
    else if( r <= mid ) query( l , r , cur -> left , maxval , minval );
    else query( l , mid , cur -> left , maxval , minval ) , query( mid + 1 , r , cur -> right , maxval , minval );
}

ll erfen1( int x ){
    int l = x , r = n , mid , res = -1, maxval , minval;
    while( l <= r ){
        mid = (l+r)>>1 , maxval = -1 , minval = 0x7fffffff;
        query( x , mid , root , maxval , minval );
        if( maxval >= maxx && minval <= miny ) res = mid , r = mid - 1;
        else l = mid + 1;
    }
    if( res == -1 ) return -1;
    maxval = -1 , minval = 0x7fffffff , query( x  , res , root , maxval , minval );
    if(maxval == maxx && minval == miny ) return res;
    return -1;
}

ll erfen2( int x ){
    int l = x , r = n , mid , res = -1, maxval , minval;
    while( l <= r ){
        mid = (l+r)>>1 , maxval = -1 , minval = 0x7fffffff;
        query( x , mid , root , maxval , minval );
        if( maxval <= maxx && minval >= miny ) res = mid , l = mid + 1;
        else r = mid - 1;
    }
    if( res == -1 ) return -1;
    maxval = -1 , minval = 0x7fffffff , query( x  , res , root , maxval , minval );
    if(maxval == maxx && minval == miny ) return res;
    return -1;
}

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;
}

int main() {
    n = read() , maxx = read() , miny = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    root = build(1,n);
    for( ll i = 1 , l , r ; i <= n ; i ++ ){
        l = erfen1( i ) , r = erfen2(i);
        if( l != -1 && r != -1 ) cnt += r - l + 1;
    }
    cout << cnt << endl;
    return 0;
}
posted @ 2022-05-24 16:55  PHarr  阅读(30)  评论(0编辑  收藏  举报