AtCoder Regular Contest138 对于我来说难度太大,我们只看A题
目录
Acwing第46场周赛
1.取石子
两个小朋友玩取石子游戏。
第一个小朋友面前有 n1n1 个石子,第二个小朋友面前有 n2n2 个石子。
两人轮流取自己面前的石子。
第一个小朋友先手,第二个小朋友后手。
第一个小朋友每轮次最多取 k1k1 个石子,最少取 11 个石子。
第二个小朋友每轮次最多取 k2k2 个石子,最少取 11 个石子。
率先取完自己面前石子的小朋友,视为失败。
请问,两个小朋友都采取最优策略的情况下,谁会获胜?
输入格式
一行,四个整数 n1,n2,k1,k2n1,n2,k1,k2。
输出格式
如果第一个小朋友获胜,则输出
First
,如果第二个小朋友获胜,则输出Second
。数据范围
所有测试点满足 1≤n1,n2,k1,k2≤501≤n1,n2,k1,k2≤50。
输入样例1:
2 2 1 2
输出样例1:
Second
输入样例2:
2 1 1 1
输出样例2:
First
分析
先取完就会输,那么最优方案就是取的越慢越好,每次只取 1次
思路:每次最少取1个的情况下 石子数多的人获胜
由于先手所以石子数相同时 第2个人获胜
#include<iostream>
using namespace std;
int main(){
int n1,n2,k1,k2;
cin>>n1>>n2>>k1>>k2;
cout<<(n1<=n2?"Second":"First")<<endl;
return 0;
}
2.卡牌
有 nn 张卡牌,编号 1∼n1∼n。
每张卡牌的正面和背面都各有一个数字。
第 ii 张卡牌的正面数字为 aiai,背面数字为 bibi。
初始时,所有卡牌都正面朝上,显示正面的数字。
现在,你可以将其中一些卡牌翻面,使其显示背面的数字,要求:
- 至少有 kk 张卡牌保持正面朝上。
- 所有卡牌显示的数字之和尽可能小。
输出所有卡牌显示的数字之和的最小可能值。
输入格式
第一行包含两个整数 n,kn,k。
第二行包含 nn 个整数 a1,a2,…,ana1,a2,…,an。
第三行包含 nn 个整数 b1,b2,…,bnb1,b2,…,bn。
输出格式
一个整数,表示所有卡牌显示的数字之和的最小可能值。
数据范围
前 66 个测试点满足 1≤n≤101≤n≤10。
所有测试点满足 1≤n≤2×1051≤n≤2×105,0≤k≤n0≤k≤n,1≤ai,bi≤1041≤ai,bi≤104。输入样例1:
3 1 5 4 6 3 1 5
输出样例1:
10
输入样例2:
5 3 3 4 7 10 3 4 5 5 12 5
输出样例2:
25
优先队列
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
typedef pair<int,pii> pipii;
typedef pair<long long,int> pli;
const int N = 2e5+10;
ll res;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,k;
cin>>n>>k;
int a[N],b[N];
for(int i = 0;i<n;i++) cin>>a[i];
for(int i = 0;i<n;i++) cin>>b[i];
priority_queue<int,vector<int>,greater<int> > q;
for(int i = 0;i<n;i++){
res+=a[i];
q.push(b[i]-a[i]);
}
k = n - k;
while(q.size()){
if(!k) break;
int t = q.top();
q.pop();
if(t>=0) break;
res+=t;
k--;
if(!k) break;
}
cout<<res<<endl;
return 0;
}
AtCoder Regular Contest138 A
A - 较大分数社论
/
时间限制: 3 秒 / 内存限制: 1024 MB
得分 : 积分400400
问题陈述
我们有一个长度的整数序列:。下面在这个问题上,让 的分数成为 的第一项之和。此外,让我们成为输入中给定的序列的分数。NNA=(A_1,A_2,\cdots,A_N)A=(A1,A2,⋯,AN)AAKKAAssAA
您可以执行以下操作任意次数。
- 选择 两个相邻的元素并交换它们。AA
你的目标是至少得分。确定目标是否可实现。如果是,请找到实现它所需的最小操作数。s+1s+1
约束
- 2 \leq N \leq 4 \times 10^52≤N≤4×105
- 1 \leq K \leq N-11≤K≤N−1
- 1 \leq A_i \leq 10^91≤Ai≤109
- 输入中的所有值都是整数。
输入
输入从标准输入以下列格式提供:
NN KK A_1A1 A_2A2 \cdots⋯ A_NAN
输出
如果目标无法实现,请打印 。如果可实现,请打印实现它所需的最小操作数。
-1
示例输入 1 复制
复制4 2 2 1 1 2
示例输出 1 复制
复制2
我们有。以下操作序列使分数至少为 。s=2+1=3s=2+1=344
- (2,1,1,2) \to ((2,1,1,2)→(交换和交换和A_3A3A_4)\to (2,1,2,1) \to (A4)→(2,1,2,1)→(A_2A2A_3)\to (2,2,1,1)A3)→(2,2,1,1)
该目标在一次操作中无法实现,因此所需的最小操作数为 。22
示例输入 2 复制
复制3 1 3 2 1
示例输出 2 复制
复制-1
示例输入 3 复制
复制20 13 90699850 344821203 373822335 437633059 534203117 523743511 568996900 694866636 683864672 836230375 751240939 942020833 865334948 142779837 22252499 197049878 303376519 366683358 545670804 580980054
示例输出 3 复制
复制13
我想吐槽一句,这叫签到题???
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1000000007;
using P=pair<ll,ll>;
const ll inf = 1ll<<60;
int main() {
ll n,k;
cin >> n >> k;
vector<P>a(n);
for(ll i=0;i<n;i++){
ll x;
cin >> x;
a[i]={x,-i};
}
sort(a.begin(),a.end());
for(ll i=0;i<n;i++){
a[i].second*=-1;
}
ll now=-inf;
ll ans=inf;
for(ll i=0;i<n;i++){
if(a[i].second<k){
now=max(now,a[i].second);
}else{
if(now!=-inf){
ans=min(ans,a[i].second-now);
}
}
}
if(ans==inf){
cout << -1 << endl;
}else{
cout << ans << endl;
}
}