CF282A Bit++
题意
其中X++,++X表示把 X 加 1 ,X–,–X表示把 X 减 1 。
思路
- 判断是加还是减
- 进行计算
- 最后输出结果
坑点
- 无
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int ans=0;//记录答案
while(n--)
{
string s;
cin>>s;
if(s=="X++"||s=="++X")//判断加减
{
ans++;
}
else{
ans--;
}
}
cout<<ans;
return 0;
}
总结
签到题
CF466A Cheap Travel
题意
Ann需要搭n次地铁。她有两种票可供选择:第一种票a卢布一张,可以搭一次地铁;第二种票b卢布一张,可以搭m次地铁。问:Ann最少需要多少卢布才能搭n次地铁?
思路
- 要求搭n次地铁需要的最少钱
- 就要找单价最便宜的买,比较两种票价的大小
- 可以买的次数超出n次
坑点
- 无
代码
#include<iostream>
using namespace std;
int main()
{
int n,m,a,b;
cin>>n>>m>>a>>b;
if(float(b/m)>=a)//如果b的单价大于a的单价全全买a
{
cout<<a*n;
}
else
{
cout<<n/m*b+min(b,n%m*a);//否则先买b,剩余的判断是b便宜还是单买a便宜
}
return 0;
}
总结
简单思维,贪心
CF892B Wrath
题意
有n个罪犯排成一排,其中第i个人拿着一个长 L i的爪子。铃声敲响时每个人都会将其前面的一些人杀掉。所有人在同一时刻杀掉其他人。也就是说,如果j<i 并且j>=i-Li,那么第i个人将会杀掉第j 个人。现在给出每个爪子的长度,你要找出铃响之后还有多少人幸存。
思路
- 依次遍历每个人杀掉的人,最后计算发现会超时
- 可以从最后的一个人往前推,将左端点作为判断依据
- 判断与左端点的不同,进行计算
坑点
- 无
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N];
int main()
{
int n;
cin>>n;
int ans=0;
int minn=999999999;//初始左端点要尽可能的大
for(int i=1;i<=n;i++)
{
cin>>a[i];//依次输入每个人的长度
}
for(int i=n;i>=1;i--)//从后往前遍历
{
if(minn>i)//如果当前人的位置小于左端点,这个人就是幸存的
{
ans++;
}
minn=min(minn,i-a[i]);//更新左端点
}
cout<<ans;
return 0;
}
总结
双指针、贪心,思维题
CF816B Karen and Coffee
题意
她有 n 本食谱,第 ii 本食谱包含两个数 l_i,r_i,表示这本食谱推荐用 [l_i,r_i] 之间的温度(包含 l_i.r_i)来煮咖啡。
Karen 认为一个温度 a是可接受的当且仅当有 ≥k 本食谱推荐用 a 来煮咖啡。
Karen 有 q 个问题,每个问题用一对正整数 a_i,b_i来表示,表示她问 [a i ,b i ] 之间有多少个温度是可接受的。
思路
- 利用差分寻找每个点的推荐的次数
- 判断每个点推荐次数是否满足,放入数组,再计算前缀和,统计每个点的前缀和
- 最后将区间内的次数计算出
坑点
- 无
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int a[N],s[N],f[N],s2[N];
int main()
{
int n,k,q;
cin>>n>>k>>q;
int maxn=0;
for(int i=1;i<=n;i++)
{
int l,r;
cin>>l>>r;
a[l]+=1;a[r+1]-=1;//利用差分将区间内的点都加1
maxn=max(maxn,r);
}
for(int i=1;i<=maxn;i++)
{
s[i]=s[i-1]+a[i];//记录前缀和,就是统计每个点的推荐次数
}
for(int i=1;i<=200000;i++)
{
if(s[i]>=k)//遍历判断是否满足推荐次数
{
f[i]+=1;//放入数组记录
}
else{
f[i]=0;
}
}
for(int i=1;i<=200000;i++)
{
s2[i]=s2[i-1]+f[i];//计算每个点前缀和。
}
for(int i=1;i<=q;i++)
{
int a,b;
cin>>a>>b;
cout<<s2[b]-s2[a-1]<<endl;//判断区间内的几个点满足
}
return 0;
}
总结
差分,前缀和的运用
CF2A Winner
题意
通过每轮的加减找到获胜者的名称。
思路
- 利用map找到最高分
- 判断谁先达到这个最高分
- 最后输出答案
坑点
- 如果两名或两名以上的玩家在比赛结束时都有最大的分数 m,那么其中首先获得至少 m 分的玩家胜利。
代码
#include<iostream>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int N=1e6+10;
int x[N];//记录每轮的数值
string s[N];//每个人的名字
int main()
{
int n;
cin>>n;
map<string,int>mp;//记录每个人最终的分值
map<string,int>mp2;//如有两个或两个以上都是最高分,寻找最先到达这个分数的人
int maxn=-9999999999;
for(int i=1;i<=n;i++)
{
cin>>s[i]>>x[i];
mp[s[i]]+=x[i];
}
for(int i=1;i<=n;i++)//寻找最高分
{
maxn=max(maxn,mp[s[i]]);
}
for(int i=1;i<=n;i++)//寻找最先达到这个分数的人
{
mp2[s[i]]+=x[i];
if(mp2[s[i]]>=maxn&&mp[s[i]]==maxn)
{
cout<<s[i];
break;
}
}
return 0;
}
总结
map的灵活运用