AtCoder 초급 콘테스트 190 문제 해결 보고서

주제 링크 : abc190

A-매우 원시적 인 게임

이야기

  • 다카하시와 아오키는 과자를 먹고 번갈아 가며 과자를 먹고, 그 사람이 과자가 없으면진다.
  • a는 T가 소유 한 사탕 수, b는 A가 소유 한 사탕 수, c = 0은 T가 먼저 먹는 것을 의미하고, c = 1은 A가 먼저 먹는 것을 의미합니다.
  • 출력 우승자 
  • 0≤A, B≤100

아이디어

  • A to eat first는 T가 하나를 먹었 음을 의미하므로 a + c를 놔두면 통일 된 T가 사탕을 먼저 먹습니다
  • a> b이면 T가 이기고, 그렇지 않으면 A가 이깁니다.

ac 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
    int a, b, c;
    cin >> a >> b >> c;
    a += c;
    if(a > b) puts("Takahashi");
    else puts("Aoki");
    return 0;
}

B-매직 3

이야기

  • 마술사 전투 몬스터, n 종류의 주문, 각 주문 지속 시간은 ai, 데미지는 bi
  • 몬스터가 견딜 수있는 최단 시간은 s이고 최대 피해는 d입니다.
  • 마술사에게 괴물을 성공적으로 죽 이도록 요청하십시오.
  • 범위 1≤N≤100, 1≤ai≤1e9, 1≤bi≤1e9, 1≤s≤1e9, 1≤d≤1e9

아이디어

  • 모든 주문에 ai <s 및 bi> d가 있는지 확인
  • 그리고 여기에 작업이 사용됩니다.

ac 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
    int n, s, d, flag = 0;
    scanf("%d%d%d", &n, &s, &d);
    while(n --){
        int x, y;
        scanf("%d%d", &x, &y);
        flag |= (x < s && y > d);
    }
    if(flag) puts("Yes");
    else puts("No");
    return 0;
}

C-그릇과 요리

이야기

  • n 종류의 요리, m 종류의 연어 a1, bi, k 개별 선택 요리,
  • 모든 사람은 ci와 di의 두 가지 선택이 있습니다. 선택한 후 얼마나 많은 연어가 충족되는지 확인하십시오.
  • 최대 몇 개 일치하는지 물어보십시오
  • 범위 : 2≤N≤100, 1≤M≤100, 1≤Ai <Bi≤N, 1≤K≤16, 1≤Ci <Di≤N

아이디어

  • 상태 압축
  • 최대 16 명만 있기 때문에 모든 상황을 바이너리로 열거 할 수 있습니다. 0은 첫 번째 접시를 선택하고 1은 두 번째 접시를 선택하고 vis 배열을 표시하는 것을 의미합니다.
  • 그런 다음 collocation (둘 다 존재하는 경우 cnt ++)을 탐색하고 마지막으로이 cnt의 최대 값을 업데이트합니다.

ac 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[105], b[105], c[105], d[105];
int vis[105];
int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i ++){
        scanf("%d%d", &a[i], &b[i]);
    }
    int k; scanf("%d", &k);
    for(int i = 0; i < k; i ++){
        scanf("%d%d", &c[i], &d[i]);
    }
    int ans = 0;
    for(int t = 0; t < (1 << k); t ++){
        for(int i = 1; i <= n; i ++) vis[i] = 0;
        for(int i = 0; i < k; i ++){
            if((t >> i) & 1)  vis[d[i]] = 1;
            else vis[c[i]] = 1;
        }
        int cnt = 0;
        for(int i = 1; i <= m; i ++){
            if(vis[a[i]] + vis[b[i]] == 2) cnt ++;
        }
        ans = max(ans, cnt);
    }
    printf("%d\n", ans);
    return 0;
}

D-계단 시퀀스

이야기

  • n을주고 몇 개의 산술 시리즈를 형성 할 수 있는지, 허용 오차 d는 1이고 시리즈의 합은 n입니까?
  • 1≤N≤1e12

아이디어

  • 산술 시퀀스의 합계 공식은 S = n * a0 + n * (n-1) * d / 2입니다.
  • d = 1이면 S는 항의 수 n과 관련되고 첫 번째 항은 a0이고, S는 알려진 다음 n을 사용하여 a0을 나타냅니다. a0 = S / n- (n-1) / 2-> 2a0 = 2S / n + 1-n
  • a0은 정수이므로 2S / n + 1-n은 짝수이고 n은 2S의 인수입니다.
  • \ sqrt {n}조건을 만족하는 n의 수를 찾기 위해 O ( ) 시간을 실행 합니다.

ac 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
    ll n; cin >> n;
    int cnt = 0;
    n <<= 1;
    for(int i = 1; i <= sqrt(n); i ++){
        if(n % i == 0){
            if((n / i + 1 - i) % 2 == 0) cnt ++;
            ll d = n / i;
            if(i == d) continue;
            if((n / d + 1 - d) % 2 == 0) cnt ++;
        }
    }
    cout << cnt << endl;
    return 0;
}

F-시프트 및 반전

이야기

  • 0에서 n-1까지 n 개의 배열을 제공하면이 배열은 n-1만큼 왼쪽으로 회전합니다.
  • 이 과정에서 어레이의 역 번호 쌍이 무엇인지 물어보십시오.
  • 역수 쌍, i <j, ai> aj를 만족하는 쌍의 수 <i, j>
  • 2≤N≤3 × 1e5

아이디어

  • ans의 초기 역순은 트리 배열 또는 병합 정렬로 수행됩니다. 여기에 트리 배열이 있습니다.
  • 예를 들어, {2, 0, 1, 3} 왼쪽으로의이 순환 이동 쌍은 {0, 1, 3, 2}가됩니다. 즉, 2가 뒤로 이동 한 다음 이제 2보다 작은 숫자가 왼쪽으로 이동, 역순 a1의 쌍이 적고 2보다 큰 숫자도 왼쪽으로 이동하며 역순으로 a2 쌍이 더 많이 있습니다.
  • 완전한 순열이기 때문에 2보다 작은 숫자 a1은 2 개의 쌍을 가지며 2보다 큰 숫자는 4-1-2 쌍을 가지므로 ans-a1 + a2 만 필요합니다.
  • 역순 쌍의 최대 값은 n * (n-1) / 2이므로 int로 폭발하고 long long을 열어야합니다.

ac 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) x & -x
const int maxn = 3e5 + 5;
int c[maxn], n;
void add(int x){
    for(int i = x; i <= n; i += lowbit(i))
        c[i] ++;
}
int query(int x){
    int ans = 0;
    for(int i = x; i > 0; i -= lowbit(i))
        ans += c[i];
    return ans;
}
int a[maxn];
int main(){
    ll ans = 0; cin >> n;
    for(int i = 1; i <= n; i ++){
        cin >> a[i]; a[i] ++;
        //由于树状数组不能加0,所以a[i]需要加1,那么下面的d1就要对应的+1, d2要对应的-1
        add(a[i]);
        //query求的是小于等于a[i]的数的个数,i是现在有的个数
        //那么现在要求的是逆序对,也就是要求前面比他大的数的个数,那么就是i-query
        ans += i - query(a[i]); 
    }
    int d1 = 0, d2 = 0;
    for(int i = 1; i <= n; i ++){
        cout << ans << endl;
        d1 = n - a[i], d2 = a[i] - 1;
        ans += d1 - d2;
    }
    return 0;
}

 

추천

출처blog.csdn.net/weixin_43911947/article/details/113448497