Codeforces Round 353 div2 675ABCDE

Codeforces Round 353 div2
通过数: 2
A:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int a, b, c;
    while(scanf("%d%d%d", &a, &c, &b) != EOF) {
        if((c - a) < 0 && b > 0) printf("NO\n");
        else if((c - a) > 0 && b < 0) printf("NO\n");
        else if(b == 0) {
            if(a == c) printf("YES\n");
            else printf("NO\n");
        }
        else if((c - a) % b == 0) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

B:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
int main()
{
    int n, a, b, c, d;
    while(scanf("%d%d%d%d%d", &n, &a, &b, &c, &d) != EOF) {
        int mmin = 1, mmax = n;
        mmin = max(mmin, 1 + c - b);
        mmin = max(mmin, 1 + d - a);
        mmin = max(mmin, 1 + d - a + c - b);
        mmin = max(mmin, 1 + d - a + c - b + a - d);

        mmax = min(mmax, n + c - b);
        mmax = min(mmax, n + d - a);
        mmax = min(mmax, n + d - a + c - b);
        mmax = min(mmax, n + d - a + c - b + a - d);

        long long len = max(mmax - mmin + 1, 0);
        printf("%I64d\n", len * n);
    }

    return 0;
}

C:
/*
对整个数组实现尽可能多的分组,答案为(n-组数)
因此求前缀和
若sum[j] == sum[i],则说明[i,j]可以形成一个单独分组
那么假设从前遍历至最后,sum[k] = val出现了cnt次
则此时前缀和后缀形成一个分组,中间有cnt - 1个分组
则此时答案为n - cnt
*/

#include <bits/stdc++.h>
using namespace std;
#define LL long long
map<LL,int>cnt;
int main()
{
    int n;
    LL sum = 0;
    scanf("%d", &n);
    int ans = n;
    cnt.clear();
    for(int i = 1 ; i <= n ; i++) {
        int u;
        scanf("%d", &u);
        sum += u;
        cnt[sum]++;
        ans = min(ans, n - cnt[sum]);
    }
    printf("%d", ans);
    return 0;
}

D:
/*
根据BST的性质做题
假设当前已经形成了一定子树,设之前插入的点形成有序数组array[i]
则当前插入数的位置k,一定有a[i] > array[k - 1] && a[i] < array[k]

先假设array[k-1]和array[k]有公共祖先,但是此公共祖先lca有array[k-1]<lca<array[k],不合题意
则k-1和k一定为祖先和儿子的关系,他们要么k-1有右儿子,要么k有左儿子
完毕

*/

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef pair<int,int> pii;
const int MAXN = 100000 + 5;
int a[MAXN], n;
set<int>S, lson, rson;
int main()
{
    while(scanf("%d", &n) != EOF) {
        for(int i = 1 ; i <= n ; i++) scanf("%d", a + i);
        S.clear();
        lson.clear(), rson.clear();
        S.insert(a[1]);
        for(int i = 2 ; i <= n ; i++) {
            auto it = S.upper_bound(a[i]);
            int res;
            if(it != S.end() && lson.count(*it) == 0) {
                res = *it;
                lson.insert(*it);
            }
            else {
                it--; res = *it;
                rson.insert(*it);
            }
            printf("%d%s", res, i == n ? "\n" : " ");
            S.insert(a[i]);
        }
    }
    return 0;
}

E:
/*
dp[i] = dp[j] + (n - i) - (a[i] - j)
j是[i+1,a[i]]区间内a[j]最大的一个。由于a[a[i]] >= a[i] + 1,故最大值大于a[i]
*/

#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fi first
#define se second
typedef pair<int,int> pii;
const int MAXN = 100000 + 5;
int n, a[MAXN];
pii dp[MAXN * 4];
void pushup(int o){dp[o] = max(dp[(o << 1) | 1], dp[o << 1]);}
void build(int o, int l,int r)
{
    if(l == r) {
        dp[o] = mp(a[l], l);
    }
    else {
        int mid = (l + r) >> 1;
        build(o << 1, l, mid);
        build((o << 1) | 1, mid + 1, r);
        pushup(o);
    }
}
pii query(int o, int l, int r, int L, int R)
{
    if(R == n) return mp(-1, n);
   if(l >= L && r <= R) return dp[o];
   else {
        int mid = (l + r) >> 1;
        pii res = mp(-2, 0);
        if(mid >= L) res = max(res, query(o << 1, l, mid , L, R));
        if(mid < R) res = max(res, query((o << 1) | 1, mid + 1, r, L, R));
        return res;
   }
}
long long re[MAXN];
int main()
{
    while(scanf("%d", &n) != EOF) {
        for(int i = 1 ; i < n ; i++) scanf("%d", a + i);
        build(1, 1, n - 1);
        long long res = 0;
        re[n] = 0;
        for(int i = n - 1 ; i >= 1 ; i--) {
            if(i == n - 1) {
                re[n - 1] = 1;
                continue;
            }
            pii p = query(1, 1, n - 1, i + 1, a[i]);
            int mark = p.se;
            re[i] = re[mark] - (a[i] - mark) + n - i;
//            if(a[i] >= n) re[i] = min(re[i], (long long)n - i);
//            printf("i = %d, mark = %d, re[i] = %d\n", i, mark, re[i]);
            res += re[i];
        }
        printf("%I64d\n", res + 1);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值