codeforces educational round 66

https://codeforces.com/contest/1175

https://codeforces.com/contest/1175/standings

A:From Hero to Zero

题意:一个数k,每次可以减1,或者除以k(只有当被k整除的时候),求变为0的次数,贪心

 

B:Catch Overflow!相当于给了一个for的伪代码,求最后结果,结果大于 1<<32的时候输出overflow

使用栈来做,有一个技巧,由于最多有10^5个循环,因此我们使用longlong保存结果,如果当前的要加的数大于1 <<32,取1<<32,这样最后的结果不会爆long long。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
using namespace std;

#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define reps(i, a, b) for(int i = (a); i < (b); i++)
#define pb push_back
#define ps push
#define mp make_pair
#define CLR(x,t) memset(x,t,sizeof x)
#define LEN(X) strlen(X)
#define F first
#define S second
#define Debug(x) cout<<#x<<"="<<x<<endl;


const double euler_r = 0.57721566490153286060651209;
const double pi = 3.141592653589793238462643383279;
const double E = 2.7182818284590452353602874713526;
const int inf = ~0U >> 1;
const int MOD = int (1e9) + 7;
const double EPS = 1e-6;

typedef long long LL;

const LL INF = 1ll << 32;
LL res = 0;
int main() {
    ios::sync_with_stdio (false);
    cin.tie (0);

    int n;
    cin >> n;
    stack<LL> sta;
    sta.push (1);
    for (int i = 0; i < n; i++) {
        string t;
        cin >> t;
        if (t == "for") {
            int x;
            cin >> x;
            sta.push (min (INF, sta.top() * x));
        } else if (t == "end") {
            sta.pop();
        } else {
            res += sta.top();
        }


    }

    if (res >= INF) {
        cout << "OVERFLOW!!!" << endl;
    } else {
        cout << res << endl;
    }
    return 0;
}

C:Electrification

题意:给了x轴上的一些点,让你选一个点,求出各个点到x的距离,然后排序后使得第k小的值尽量小。

我们顺序枚举两个点的位置[1, k], [2, k+1], [3, k+2].... 

以区间[1, k]距离,我们取第一个点和第k个点的中位数,那么所有n个点到这个点的距离排序后第j小的值应该是min(a[k] - mid, mid - a[1])。

取所有结果中最小的那个。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
using namespace std;

#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define reps(i, a, b) for(int i = (a); i < (b); i++)
#define pb push_back
#define ps push
#define mp make_pair
#define CLR(x,t) memset(x,t,sizeof x)
#define LEN(X) strlen(X)
#define F first
#define S second
#define Debug(x) cout<<#x<<"="<<x<<endl;


const double euler_r = 0.57721566490153286060651209;
const double pi = 3.141592653589793238462643383279;
const double E = 2.7182818284590452353602874713526;
const int inf = ~0U >> 1;
const int MOD = int (1e9) + 7;
const double EPS = 1e-6;

typedef long long LL;

const int N = 200010;
int a[N];
int n, k;

int main() {
    ios::sync_with_stdio (false);
    cin.tie (0);
    int T;
    cin >> T;
    while (T--){
        cin >> n >> k;
        for (int i = 1; i <= n; i++) cin >> a[i];
        int res = -1;
        int mi = 0x7f7f7f7f;
        for (int i = 1; i <= n; i++) {
            int j = i + k;
            if (j > n) continue;
            int mid = (a[i] + a[j]) / 2;
            int dis = max(a[j] - mid, mid - a[i]);
            if (dis < mi) {
                mi = dis;
                res = mid;
            }
        }
        cout << res << endl;


    }
    return 0;
}

D:Array Splitting

题意:把数组分为连续的几段后,求题目中的表达式的最大值。

可以运用下前缀和的思想,以及稍微验算下。

发现其实就是倒着求下前缀和,然后求最大的k - 1个前缀和的(似乎说后缀和更加合适)值 ,再加上整个数组的和。

#include<bits/stdc++.h>

using namespace std;

const int N = 300009;

int n, k;
int a[N];

int main(){
	cin >> n >> k;
	for(int i = 0; i < n; ++i)
		cin >> a[i];
	
	long long sum = 0;
	vector <long long> v;
	for(int i = n - 1; i >= 0; --i){
	    sum += a[i];
	    if(i > 0) v.push_back(sum);
	}
	
	long long res = sum;
	
	sort(v.begin(), v.end());
	reverse(v.begin(), v.end());
	
	
	for(int i = 0; i < k - 1; ++i)
	    res += v[i];
	    
	cout << res << endl;
	return 0;
}

E:Minimal Segment Cover

题意:给了一些线段,有一些询问,每个询问给了一个区间,问最少选择多少个线段可以覆盖这个区间。

因为n和m都达到了10^5,贪心的做法不能通过本题。

看了别人的题解似乎是采用f[i][j],表示从i开始走2^j个区间能达到的最大点。倍增思想,然后做了。。我不太熟练,没写出来。后面再补吧。

参考:bzoj1178,https://www.cnblogs.com/wxyww/p/CF1175E.htmlhttps://www.cnblogs.com/CJLHY/p/10982809.html

 

F:The Number of Subpermutations

题意:给了长度为n的数组,求有多少个子区间里的数可以成一个排列. n<=3*10^5, 1<=a[i] <=n

input:

8
2 4 1 3 4 2 1 2

output:

7

解析:有7个区间里的满足要求,分别是[1,4], [3,3] [3,6] [4,7][6,7] [7,7] [7,8]

不会做

 

G:Yet Another Partiton Problem

题意:给了长度为n(n <=2*10^4)的数组,要分为k个连续子区间,每个区间a_l, a_(l+1),....a_r的和定义为 (r-l+1)*max(a_l,a_l+1...a_r), 求结果的最小值

input:

4 2
6 1 7 4
output:

25
解释: 617 | 4 result = 3 * max(6, 1, 7) + 1 *4 = 25

不会做

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值