B-Voting
题意:
支持D者可以使后面或前面任意支持R者永久不能参与投票。反之同理。
思路一:
使用队列进行模拟。
特点:
思路简单清晰(看到答案之后),但不易想到,需要积累经验;
代码如下:
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
char v[200005];
int n;
queue<int>r,d;
int main(){
scanf("%d%s",&n,v);
for(int i=0;i<n;i++){
if(v[i]=='R')
r.push(i);
else
d.push(i);
}
while(!r.empty()&&!d.empty()){
if(r.front()<d.front())
r.push(r.front()+n);
else
d.push(d.front()+n);
d.pop();
r.pop();
}
if(r.empty())
printf("D");
else
printf("R");
return 0;
}
思路二:
枚举遍历投票过程;
特别注意:
区分可以消除的数量和实际的数量,如:d,nd;
模拟过程不止一次,要利用循环直到只剩一个人投票;
特点:
思路简单,容易想到,但没有注意细节(见特别注意)极易卡住(一直WA);
代码如下:
#include<iostream>
#include<utility>
using namespace std;
int main() {
int n;
cin >> n;
int nd = 0, nr = 0, d = 0, r = 0;
pair<bool, char> table[200005];
char ch;
for (int i = 0; i < n; ++i) {
cin >> ch;
table[i].first = 1;
table[i].second = ch;
if (ch == 'D') {
nd++;
} else {
nr++;
}
}
while (nd&&nr) {
for (int i = 0; i < n; i++) {
if (table[i].first == 0) {
continue;
}
if (table[i].second == 'D'&&nr) {
if (r != 0) {
table[i].first = 0;
r--;
nd--;
} else {
d++;
}
}
if (table[i].second == 'R'&&nd) {
if (d != 0) {
table[i].first = 0;
d--;
nr--;
} else {
r++;
}
}
}
}
if (nd) {
cout << "D";
} else {
cout << "R";
}
return 0;
}
C-K-Dominant Character
题意:
在字符串s中找到一个数字k保证s字符串中k长度的子字符串都含有同一个字母。
思路:
遍历a到z,然后依次找出出现本字母的最小长度。
代码如下:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string s;
cin>>s;
int l=s.size();
char m='a';
int k1=INT_MAX;
for(int i=0;i<26;i++){
int k2=0;
char ma=m+i;
int link=1;
for(int j=0;j<l;j++){
if(s[j]==ma) link=1;
else link++;
k2=max(link,k2);
}
k1=min(k1,k2);
}
cout<<k1<<endl;
return 0;
}
D-Frodo and pillows
题意:
n个人,m个枕头,frodo在第k个床;
分枕头使得frodo获得最多枕头并输出;
相邻两个人枕头差小于2;
思路:
对frodo所获枕头数进行二分查找;
特别注意:可能存在mid不够递减的情况;要分情况讨论赋值;
代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k,ans;
bool check(int x)
{
int s1=0,s2=0;
if(x>=k)
{
s1=(x*2-k+1)*(k)/2;
}
else
{
s1=(1+x)*x/2+k-x;
}
int k1=n-k+1;
if(x>=k1)
{
s2=(x*2-k1+1)*(k1)/2;
}
else
{
s2=(1+x)*x/2+k1-x;
}
if(s1+s2-x<=m) return 1;
else return 0;
}
signed main()
{
cin>>n>>m>>k;
int l=1,r=m;
while(l<=r)//二分
{
int mid=(l+r)/2;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
cout<<ans;
}
E-Energy exchange
题意:
需要将能量传递让所有电池电量相等,但每次都要损失k%。
思路:
计算出多出电量和缺少电量的总和;
如果缺少电量正好比多出电量损失 k% ,那么答案就是当前单个电量。
需要二分枚举单个电量的值即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,k;
double a[N];
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lf",&a[i]);
}
// 二分
double l=0,r=1e3;
while(r-l>1e-8){
double mid=(r+l)/2;
double s1=0,s2=0;
for(int i=1;i<=n;i++){
if(a[i]<mid) s1+=mid-a[i];
else s2+=a[i]-mid;
}
if(s1>s2*(100-k)/100) r=mid;
else l=mid;
}
printf("%.8lf",l);
return 0;
}
总结:
该组题目主要用到贪心和二分,许多题目思路新颖,值得细细推敲;
PS:
如果对你有帮助的话,点个赞谢谢喵!