cf#700(div.2)

B题

题意
你有一个英雄,攻击力为A,生命值为B。(没有经验、金币等机制,攻击力与生命值不可提高)

游戏中有n只怪,怪的攻击力为a[i],生命值为b[i]。

每次你可以选择一个怪攻击,攻击后你的生命值变为B-a[i],怪的生命值变为b[i]-A。

不论你是否死亡,如果你能消灭所有的怪,获得胜利。否则失败。

题解

别想复杂,模拟即可

由于最后,不管英雄死活,只要怪全死就好了,对于杀死所有怪物的最后一刀,只要当时英雄血量大于0,就好了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e9 + 7;
const int MAX = 1e5 + 10;
ll a[MAX];
ll b[MAX];

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        ll A, B, n;
        scanf("%lld%lld%lld", &A, &B, &n);
        ll max_damage = 0;
        for(int i = 0; i < n; i++) {
            scanf("%lld", &a[i]);
            max_damage = max(max_damage, a[i]);
        }
        for(int i = 0; i < n; i++) scanf("%lld", &b[i]);
        for(int i = 0; i < n; i++) {
            B -= (b[i] + A - 1) / A * a[i];
        }
        if(B + max_damage > 0) printf("YES\n");
        else printf("NO\n");
    }
}

C题

题意

交互题,输入一个n,会有一个序列(序列中的数就是1…n乱序排列),然后你可以询问最多100次,来找出序列中一个局部最小值(就是这个数小于它左右两边的数)

题解

原本我找三个判断趋势,实际上最多寻找100次,1e5刚刚好卡住34次,每次找三个,最多只能找33次。

呜呜呜

其实a[0] = a[n+1] = INF,就暗示了,头是递减,尾是递增,任意找两个,如果是递增,那么与头就一定有最小极值点,同理。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
using namespace std;
const int MAX = 1e5 +10;
const int INF = 1e9 + 7;
int a[MAX];
int main(){
    int n;
    scanf("%d", &n);
    int L = 1, R = n;
    a[0] = INF, a[n + 1] = INF;
    int mid;
    for(int i = 0; i < 100; i++) {
        int mid = (L + R) / 2;
        printf("? %d\n", mid);
        fflush(stdout);
        scanf("%d", &a[mid]);
        if(mid + 1 <= n) {
            printf("? %d\n", mid + 1);
            fflush(stdout);
            scanf("%d", &a[mid + 1]);
        }
        if(L == R) {
            printf("! %d\n", L);
            break;
        }
        if(a[mid] < a[mid + 1]) R = mid;
        else L = mid + 1;
    }
}

D1题目

题意

把一个长度为n的数组分成两个子数组a,b,要求seg(a)+seg(b) 最大 ,seg(a)表示数组中不同的连续段,例如[1,1,2,2,3,3,3,1] 连续段就是[1,2,3,1] 长度是4

题解

这道题目想明白关键点是尽可能少出现连续一样的,那么其实只需要关注每个数组的最后一个值

设数组1的最后一个值为v1, 数组2的最后一个值为v2

1.如果要插入的值a,不等于v1,v2,且v1 = v2那么任意插

2.如果与v1 或者 v2相等,那就插到不想等的后面去

3.如果都不相等,要使得再次出现v1或者v2时,v1或者v2已经被替换掉,所以先替换掉v1、v2中在待插入的数组中先出现的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
using namespace std;
const int MAX = 1e5 +10;
const int INF = 1e9 + 7;
vector<int>pos[MAX];//每个数字出现的位置
int cnt[MAX];//每个数字出现了几次
int a[MAX];

int main(){
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
        pos[a[i]].push_back(i);
    }
    int v1 = -1, v2 = -1;
    ll ans = 0;
    for(int i = 0; i < n; i++) {
        cnt[a[i]]++;
        if(v1 == v2) {
            if(a[i] != v1) {
                v1 = a[i];
                ans++;
            }
        }
        else if(v1 == a[i] && v2 != a[i]) {
            v2 = a[i];
            ans++;
        }
        else if(v2 == a[i] && v1 != a[i]) {
            v1 = a[i];
            ans++;
        }
        else {
            int next_v1 = n + 1, next_v2 = n + 1;
            if(cnt[v1] < pos[v1].size()) {
                next_v1 = pos[v1][cnt[v1]] ;
            }
            if(cnt[v2] < pos[v2].size()) {
                next_v2 = pos[v2][cnt[v2]];
            }
            if(next_v1 < next_v2) {
                v1 = a[i];
                ans++;
            }
            else {
                v2 = a[i];
                ans++;
            }
        }
    }
    printf("%lld\n", ans);
}

D2题目

题意

与D1相似,问最小

题解

与上题目类似,改一点点就好了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
using namespace std;
const int MAX = 1e5 +10;
const int INF = 1e9 + 7;
vector<int>pos[MAX];
int a[MAX];
int cnt[MAX];

int main(){
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
        pos[a[i]].push_back(i);
    }
    int v1 = -1, v2 = -1;
    ll ans = 0;
    for(int i = 0; i < n; i++) {
        cnt[a[i]]++;
        if(v1 == v2) {
            if(v1 != a[i]) {
                v1 = a[i];
                ans++;
            }
        }
        else if(v2 != a[i] && v1 == a[i]) {
            v1 = a[i];
        }
        else if(v1 != a[i] && v2 == a[i]) {
            v2 = a[i];
        }
        else {
            int next_v1 = n + 1, next_v2 = n + 1;
            if(cnt[v1] < pos[v1].size()) {
                next_v1 = pos[v1][cnt[v1]];
            }
            if(cnt[v2] < pos[v2].size()) {
                next_v2 = pos[v2][cnt[v2]];
            }
            if(next_v1 < next_v2) {
                v2 = a[i];
                ans++;
            }
            else {
                v1 = a[i];
                ans++;
            }
        }
    }
    printf("%lld\n", ans);
}

总结

B题卡住了,出的太慢;想复杂了呀,唉,应该想到AB题怎么可能出的难呢!!

C题目交互题,没有经验,所以想复杂了,明明是简单的二分,呜呜呜,笨蛋啊

D1想明白问题的关键,其实不难

D2完完全全与D1类似啊,一点也不难,呜呜呜

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值