2022.07.08 暑假集训 个人排位赛(三)
赛后反省
动态规划的敏感度不够,还是一直在错的方法死磕。然后另外一道题对于一些特征不太敏感,已经接近正解了,就差一步。
继续加油。
Problem A
出处
Codeforces-689D
题解
ST表+二分
利用ST表之后,枚举区间的左坐标。当右区间不断扩大的时候,最大值是一个递增序列,最小值是一个递减序列。所以用两次二分,来找到在两段序列中最大值和最小值相等的区间是否存在。
代码
// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long
using namespace std;
const int N = 1e6 + 6;
int n, T = 1;
int a[N][22];
int b[N][22];
int get_max(int x, int y) {
int mid = log2(y - x + 1);
return max(a[x][mid], a[y - (1 << mid) + 1][mid]);
}
int get_min(int x, int y) {
int mid = log2(y - x + 1);
return min(b[x][mid], b[y - (1 << mid) + 1][mid]);
}
bool check_L(int x, int y) {
int minn = get_min(x, y);
int maxn = get_max(x, y);
if (maxn >= minn) return true;
else return false;
}
bool check_R(int x, int y) {
int minn = get_min(x, y);
int maxn = get_max(x, y);
if (maxn > minn) return true;
else return false;
}
void ready()
{
cin >> n;
ffor(i, 1, n) {
cin >> a[i][0];
}
ffor(j, 1, 18) {
ffor(i, 1, n) {
a[i][j] = max(a[i][j - 1], a[i + (1 << (j - 1))][j - 1]);
}
}
//mst(b,INF);
ffor(i, 1, n) {
cin >> b[i][0];
}
ffor(j, 1, 18) {
ffor(i, 1, n) {
b[i][j] = min(b[i][j - 1], b[i + (1 << (j - 1))][j - 1]);
}
}
int ans = 0;
ffor(i, 1, n) {
int L = 0, R = 0;
int l = i, r = n, mid;
while (l < r) {
mid = l + r >> 1;
if (check_L(i, mid)) {
r = mid;
}
else {
l = mid + 1;
}
}
L = l;
l = i; r = n;
while (l < r) {
mid = l + r + 1>> 1;
if (check_R(i, mid)) {
r = mid - 1;
}
else {
l = mid;
}
}
R = l;
// cout << "i=" << i << ' ' << L << ' ' << R << '\n';
if (get_max(i, L) == get_min(i, R)) {
ans += R - L + 1;
}
}
cout << ans;
}
void work()
{
}
signed main()
{
IOS;
ready();
// cin>>T;
while (T--) {
work();
}
return 0;
}
Problem B
出处
Codeforces-687C
题解
动态规划。
dp[i][j]dp[i][j]dp[i][j]代表值为i时是否能被j给构造。如果能则为1,否为0。
如果dp[i][j]=1dp[i][j]=1dp[i][j]=1,那么当加入一个新的值c时,dp[i+c][j]=1dp[i+c][j]=1dp[i+c][j]=1和dp[i+c][j+c]=1dp[i+c][j+c]=1dp[i+c][j+c]=1都成立。那么转移方程也得到了。
代码
// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long
using namespace std;
const int N = 505;
bool dp[N][N];
int n, T = 1, k;
void ready()
{
cin >> n >> k;
dp[0][0] = true;
ffor(t, 1, n) {
int c;
cin >> c;
rrep(i, k, c) {
ffor(j, 0, k-c) {
if (dp[i - c][j])
dp[i][j] = dp[i][j + c] = true;
}
}
}
}
void work()
{
int ans = 0;
ffor(i, 0, k) ans += dp[k][i];
cout << ans << '\n';
ffor(i, 0, k) {
if (dp[k][i])
cout << i << ' ';
}
}
signed main()
{
IOS;
// cin>>T;
while (T--) {
ready();
work();
}
return 0;
}
Problem F
出处
Codeforces-702D
题解
思维题。
距离比较小,直接开车就到达。
如果k距离时,走路快过汽车走并且修车,那么先开车走k公里,剩下的路全都走路。
如果k距离时,走路慢过汽车走并修车,那么后面每个k公里都开车,直到剩下比k公里小的路程没走时,考虑一下修车再走快还是直接走路快,进行选择即可。
代码
// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long
using namespace std;
int n, T = 1;
int d,k,a,b,t;
void ready()
{
cin>>d>>k>>a>>b>>t;
if(d<=k){
cout<<d*a;
return;
}
if(a*k+t>b*k){
int ans=k*a;
d-=k;
ans+=d*b;
cout<<ans;
return;
}
else{
int cnt=d/k;
int ans=cnt*a*k + (cnt-1)*t;
d=d%k;
if(cnt==0) ans=0;
if(a*d+t>=b*d)
ans+=b*d;
else{
ans+=a*d;
if(cnt) ans+=t;
}
cout<<ans;
}
}
void work()
{
}
signed main()
{
IOS;
ready();
// cin>>T;
while (T--) {
work();
}
return 0;
}
Problem G
出处
Codeforces-1234A
题解
平均数,上进位。
代码
// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long
using namespace std;
int n, T = 1;
void ready()
{
}
void work()
{
cin>>n;
int sum=0;
ffor(i,1,n){
int x;
cin>>x;
sum+=x;
}
int ans=(sum+n-1)/n;
cout<<ans<<'\n';
}
signed main()
{
IOS;
ready();
cin>>T;
while (T--) {
work();
}
return 0;
}