https://codeforces.com/contest/1175
https://codeforces.com/contest/1175/standings
题意:一个数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;
}
题意:给了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;
}
题意:把数组分为连续的几段后,求题目中的表达式的最大值。
可以运用下前缀和的思想,以及稍微验算下。
发现其实就是倒着求下前缀和,然后求最大的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;
}
题意:给了一些线段,有一些询问,每个询问给了一个区间,问最少选择多少个线段可以覆盖这个区间。
因为n和m都达到了10^5,贪心的做法不能通过本题。
看了别人的题解似乎是采用f[i][j],表示从i开始走2^j个区间能达到的最大点。倍增思想,然后做了。。我不太熟练,没写出来。后面再补吧。
参考:bzoj1178,https://www.cnblogs.com/wxyww/p/CF1175E.html,https://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
不会做