CFEDU 35 A - D 题解

传送门

A: 求最小的元素相隔的距离最小是多少.
记录最小值的位置, 扫一遍就行啦.
AC Code

const int maxn = 1e5+5;
int cas=1;
int a[maxn];
void solve()
{
    int n ;
    while(cin >> n){
        int mi = inf;
        for (int i = 1 ; i<= n ; i ++) {
            cin >> a[i];
            mi = min(mi, a[i]);
        }
        int cnt = 0, pre , ans = inf;
        for (int i = 1 ; i <= n ; i++) {
            if (a[i] == mi) {
                cnt++;
                if (cnt == 1) pre = i;
                else ans = min(ans, i - pre), pre = i;
            }
        }
        cout << ans << endl;
    }
}

B: n个人分两个分别被切成了a, b份的蛋糕, 每个人至少得到一份, 两个蛋糕的份数不能同时给一个人, 也就是每个人只能分到其中一个蛋糕的一部分. 问每个人分到的蛋糕最少的最大值是多少.

其实这个是概率问题, 份数多的自然人就应该要多一点才行, 但是却无法直接得到, 并且向这种简单题, 能爆就爆, 我们直接枚举人数去分这个a, b就行啦, 然后取一个max. k 个人分 a 份, 最少的那个人得到的分数是k / a.

AC Code

void solve()
{
    int n, a, b;
    while(cin >> n >> a >> b) {
        int ans = 0;
        for (int i = 1 ; i <= n-1 ; i++) {
            ans = max(ans, min(a/i, b/(n-i)));
        }
        cout << ans << endl;
    }
}

C: 给定三个灯闪烁的时间间隔(k1, k2, k3), 问是否可以找到三个时间点, 使得在max(x1, x2, x3)后每一秒都有灯在闪烁.

我们首先可以发现时间点从哪里起始并不重要, 所以我们直接选取1, 2, 3为起始点就行啦. 然后就是如果其中最大的间隔为5(如果三个间隔中2的数量<=1) , 那么就一定不可能了, 所以我们直接暴力到10 , 然后check一遍1-10中是否都亮着就行啦, 注意就是间隔小的应放在前面.
(所以像cf前面几题直接暴力就行啦!!!)
AC Code

int a[5];
int vis[20];
void solve()
{
    while(cin >> a[1] >> a[2] >> a[3]) {
        Fill(vis, 0);
        sort(a+1, a+4);
        for (int i = 1 ; i <= 10 ; i ++) {
            if (!vis[i]) {
                for (int j = i ; j <= 10 ; j+=a[1]) {
                    vis[j] = 1;
                }
                break;
            }
        }
        for (int i = 2 ; i <= 10 ; i ++) {
            if (!vis[i]) {
                for (int j = i ; j <= 10 ; j+=a[2]) {
                    vis[j] = 1;
                }
                break;
            }
        }
        for (int i = 3 ; i <= 10 ; i ++) {
            if (!vis[i]) {
                for (int j = i ; j <= 10 ; j+=a[3]) {
                    vis[j] = 1;
                }
                break;
            }
        }
        int flag = 1;
        for (int i = 1 ; i <= 10 ; i ++) {
            if (!vis[i]) {
                flag = 0 ;
                break;
            }
        }
        if (!flag) cout << "NO" << endl;
        else cout << "YES" <<endl;
    }
}

D: 给定一个序列, 给出m个修改, 每次修改一个区间[l, r] 然后翻转序列中[l, r] 的数, 问翻转后逆序对的奇偶性.

这道题只要我们知道一个定理后就很简单啦, 那就是对换一个序列的任意两个不同的位置, 其逆序对数奇偶性反向, 即奇 变 偶 , 偶 变 奇. 那么就很好做啦. 先求一遍原序列的逆序对, 然后每次求修改区间的长度然后判断一下就可以知道其奇偶性啦.

AC Code

const int maxn = 1500+5;
int c[maxn], n, a[maxn];
void add(int x){ for(;x<=n;x+=x&-x) c[x]++;}
int getsum(int x){ int res=0;for(;x;x-=x&-x) res+=c[x];return res;}
void solve()
{
    while(cin >> n) {
        Fill(c, 0);
        for (int i = 1 ; i <= n ; i++) {
            cin >> a[i];
        }
        int ans = 0;
        for (int i = n ; i >= 1 ; i--) {
            ans += getsum(a[i]-1);
            add(a[i]);
        }
        ans %= 2;
        int q;
        cin >> q;
        while(q--) {
            int l, r;
            cin >> l >> r;
            if (l != r) {
                ans = ((r - l + 1) >> 1 ) % 2 == 0 ?ans : 1 - ans;
            }
            cout << (ans == 0?"even":"odd") << endl;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值