A. Detective Book(思维)
原题链接:http://codeforces.com/contest/1140/problem/A
题意: lvan看一本页数为 n 页的书,每页书可能有秘密,其答案在相对应的页数 a[i],如果当前的所有谜团没有解决的话,lvan就会一直看下去,求出他要多少天看完。
思路: 找出当前所看到谜团的答案的最大页数,如果最大页数正好等于当前看到的页数,那就天数就加1。更精辟的说法就是求从后往前找前缀最大的数和该位置下标相同的有几个。
Code(C++):
#include <iostream>
using namespace std;
int a[10100];
int main(){
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
int ans=0,maxn=-1;
for(int i=1;i<=n;i++){
if(a[i]>maxn)
maxn=a[i];
if(maxn==i)
ans++;
}
cout<<ans<<endl;
return 0;
}
B. Good String(思维)
原题链接:http://codeforces.com/contest/1140/problem/B
题意: 给一个尖括号序列,可以选择其中一个进行操作,假如选择’>‘,那么可以删去它右边的一个字符,若是’<’,则可以删去左边一个字符。在进行选择之前可以删去一些字符,问最少删去多少个字符可使得给定的序列在操作之后为good string,即只有一种字符的字符串。
思路:
- 当第一个字符是’>’,可以将后面的序列全部删除所以不需要进行操作;或者最后一个字符是’<’,可以将前面的序列全部删除所以不需要进行操作。所以直接输出0后结束循环。
- 如果不是以上的情况,那么找到最左边的’>’,该字符左边的字符个数即要删除的个数;再找出最右边的’<’,该字符右边的字符个数即要删除的个数。输出他们的最小数即可。
Code(C++):
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int t; cin>>t;
while(t--){
int n; cin>>n;
string s; cin>>s;
if(s[0]=='>' || s[n-1]=='<')
cout<<0<<endl;
else{
int a=n-1;
for(int i=0;i<n;i++){
if(s[i]=='>'){
a=i;
break;
}
}
int b=n-1;
for(int i=n-1;i>=0;i--){
if(s[i]=='<'){
b=i;
break;
}
}
cout<<min(a,n-1-b)<<endl;
}
}
return 0;
}
C. Playlist(贪心 + 优先队列)
原题链接: http://codeforces.com/contest/1140/problem/C
题意: 给n首歌曲,每首歌都有两个特征:时长和美丽值。至多选择 k 首歌组成一个播放列表,让这个播放列表的“快乐值”最高,快乐值的计算是,集合中所有歌曲的播放时长之和,乘以集合中歌曲的最小美丽值。
思路:
- 定义一个结构体,按照美丽值 b 从大到小排序
- 用小顶堆优先队列,按照时长从小到大存歌曲长度 t
- 当选择的曲子数量超过 k 时, 弹出优先队列队首,即最小的歌曲长度 t
Code(C++):
#include <iostream>
#include <queue>
#include <algorithm>
#define ll long long
using namespace std;
const int N=3e5+100;
struct node{
int t,b;
}a[N];
bool cmp(node x,node y){
return x.b>y.b;
}
int main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i].t>>a[i].b;
sort(a+1,a+1+n,cmp);
priority_queue<ll,vector<ll>,greater<ll> >q;
ll ans=0,sum=0;
for(int i=1;i<=n;i++){
q.push(a[i].t);
sum+=a[i].t;
if(q.size()>k){
sum-=q.top();
q.pop();
}
ans=max(ans,sum*a[i].b);
}
cout<<ans<<endl;
return 0;
}
D. Minimum Triangulation(思维)
原题链接: http://codeforces.com/contest/1140/problem/D
题意: 求将一个 n 边形分解成 (n-2) 个三边形花费的最小精力,其中花费的精力是所有三角形的三顶点编号乘积的和(其中编号是按照顶点的逆时针顺序编写的)。
比赛时看不懂题目意思。。
思路: 要使所有三角形编号乘积和最小,就使编号1作为所有三角形的共同顶点。
Code(C++):
#include <iostream>
using namespace std;
int main(){
int n; cin>>n;
int ans=0;
for(int i=2;i<n;i++)
ans+=i*(i+1);
cout<<ans<<endl;
return 0;
}