A.
题意:一个键盘坏了,坏的健按一下会出两个字母,给一串这个坏键盘打出来的字母,问你哪个键有可能坏了。
思路:连续奇数不可能,连续偶数有可能。
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main()
{
string str;
int n;
int m;
int num[1005];
cin>>n;
while(n--)
{
int cnt=1;
memset(num,0,sizeof num);
cin>>str;
for(int i=1;i<=str.length();i++)
if(str[i]==str[i-1])
cnt++;
else
{
if(cnt%2==1) num[str[i-1]-'a']=1;
cnt=1;
}
for(int i=0;i<26;i++)
if(num[i]==1) cout<<char(i+'a');
cout<<endl;
}
return 0;
}
B.
题意:给你n串只含1.0字符串,问你经过任意交换后,最后能得到多少个回文串
思路:哎,本来想用贪心作的,就很麻烦,确实是境界低了,这原来就是个B题,仔细想一下,答案只能是n和n-1啊,n-1只能是n个字符串总为偶数并且1和0总书都是奇数,很简洁的一个题。
#include <iostream>
using namespace std;
int main(){
int t;
cin >> t;
while(t--){
string s;
int n, num0 = 0, k = 0;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> s;
int len = s.size();
for(int j = 0; j < len; j++){
if(s[j] == '0') num0++;
}
if(len % 2 == 1) k++;
}
if(k == 0 && num0 % 2 == 1)
cout << n-1 <<endl;
else
cout << n << endl;
}
return 0;
}
C.
题意:给一个数字,如果相邻的两个数奇偶性不同则可以交换,问你这个数字最后最小是多少。
思路:其实可以把整个数字看成多个“可交换区段”每一次改变交换区段就是由一个奇数或偶数交换后,就简单说,重新组合这个数字,而第一个数字的选择就只能是奇偶性第一次改变之前的区间中最小的,第二个数就是第二次改变前的区间,这样依次类推,这样实现起来也很简单,两个数组分别存储奇数和偶数,然后每次比较找小的就行了。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string s;
int chong;
cin>>s;
vector<int>a,b;
for(int i=0;i<s.length();i++)
{
int num=s[i]-'0';
if(num%2)
a.push_back(num);
else
b.push_back(num);
}
int i,j;
for(i=0,j=0;i<a.size()&&j<b.size();)
{
if(a[i]<b[j])
cout<<a[i];i++;
else
cout<<b[j];j++;
}
if(i<a.size())
for(;i<a.size();i++) cout<<a[i];
if(j<b.size())
for(;j<b.size();j++) cout<<b[j];
cout<<endl;
}
}
D.
题意:你有N个员工,有K元钱,每个员工有工资范围,问怎么分配才能让工资中位数最大。
思路:本来想用贪心,最小工资排序,感觉还挺好的,但是后面的最大工资无法确定能大于中位数。于是看到了二分,我还真没想到要这样做,有点呆,check的时候就先把前面后面筛选出来,前面就取最少,后面就是也取最少,求sum,如果sum<=k就返回true就再看还能再花点钱吗
#include<iostream>
#include<vector>
using namespace std;
pair<int,int>a[200005];
int t,n,k,i,j;
bool check(int mid){
int sum = 0;
vector<pair<int, int>> v;
for( i = 1; i <= n; i++){
if(a[i].second<mid)
sum += a[i].first;
else
v.push_back(a[i]);
}
ll len = v.size();
if(len < n/2+1){
return false;
}
sort(v.begin(), v.end());
for (i = 0; i < (n/2+1); i++){
sum += max(mid, v[len-i-1].first);
}
for( i = 0; i < len - (n/2+1); i++){
sum += v[i].first;
}
if(sum <= k){
return true;
}
else{
return false;
}
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
for(i=1;i<=n;i++)
cin>>a[i].first>>a[i].second;
int l=0,r=k;
while(l<=r){
int mid=(r+l)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<r<<endl;
}
E1:
题意:有n个人,每个人有各自的mi 和 pi 如果有mi个人投你,那么他也会投你,如果不是mi个人投你,若让他投你,你就得花费pi 去贿赂他,问所有人投你要花费多少。
思路:好贪心,一个个向后枚举,从n到1进行选择,如果当前人数有i个得话,就可以全投了,pi的处理其实就好的多了,我们可以用贪心的办法解决,如果说 N - size < i,那么,我们的size一定是偏大了,我们就可以去把偏大的部分给买通了,这时候就可以用优先队列去找这size里面的最小p值即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
const int maxN = 2e5 + 7;
int N;
vector<int> vt[maxn];
using namespace std;
int main()
{
int T,m,p;
cin>>T;
while(T--)
{
scanf("%d", &N);
for(int i=0; i<=N; i++) vt[i].clear();
for(int i=1; i<=N; i++) { scanf("%d%d", &m, &p); vt[m].push_back(p); }
priority_queue<int, vector<int>, greater<int>> Q;
ll ans = 0;
for(int i=N; i>=0; i--)
{
int len = (int)vt[i].size();
for(int j=0; j<len; j++) Q.push(vt[i][j]);
while(Q.size() > N - i) { ans += Q.top(); Q.pop(); }
}
printf("%lld\n", ans);
}
return 0;
}