题解
消消看
知识点:贪心,排序
题意:给定一个01串,每次可以选择一个连续的0或者1子串消除。两个人轮流消除,求双方都最优选择时,胜者是谁以及分数之差。
思路:显然不可能选择'0'子串。并且有多个'1'子串时会选择最长的那个1串。因此用贪心策略即可,预处理出所有'1'子串的长度,然后从大到小选择即可。
复杂度
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
vector<int>v;
int n,i,cnt=0;
string s;
cin>>s;
for(i=0;i<s.length();i++){
if(s[i]=='1')cnt++;
else v.push_back(cnt),cnt=0;
}
v.push_back(cnt);
sort(v.begin(),v.end());
int c1=0,c2=0;
for(i=0;i<v.size();i++){
if(i%2)c2+=v[i];
else c1+=v[i];
}
if(c1<c2)cout<<"Niumei\n"<<c2-c1<<endl;
else if(c1==c2)cout<<"Draw\n";
else cout<<"Niumei\n"<<c1-c2<<endl;
}
}赏金猎人
知识点:贪心,排序,优先队列
题意:每个人有一个战斗力和金钱。每个人只能击杀比自己战斗力低的人,并获得他的金钱。问在最多击杀 个人的前提下,每个人最多的钱是多少?
思路:对于每个人而言,只需要在战斗力比他小的人里,找出 个最大的金钱即可。观察到
的范围不超过10,因此可以用优先队列(最大堆)解决这个问题。
写代码的时候要注意细节,处理“战斗力相等”的人的时候要格外小心。
复杂度
using namespace std;
struct people{
int attack,money,id,res;
};
people a[100010];
bool cmp(people a,people b){
return a.attack<b.attack;
}
bool cmp_by_id(people a,people b){
return a.id<b.id;
}
priority_queue<int>q;
int main(){
int n,k,i,j;
cin>>n>>k;
for(i=0;i<n;i++)cin>>a[i].attack;
for(i=0;i<n;i++){
cin>>a[i].money;
a[i].id=i;
a[i].res=a[i].money;
}
sort(a,a+n,cmp);
vector<int>temp;
for(i=0;i<n;i++){
vector<int>to_be_killed;
int now=q.size();
for(j=0;j<min(k,now);j++){
a[i].res+=q.top();
to_be_killed.push_back(q.top());
q.pop();
}
for(j=0;j<to_be_killed.size();j++){
q.push(to_be_killed[j]);
}
temp.push_back(a[i].money);
to_be_killed.clear();
if(i<n-1&&a[i].attack<a[i+1].attack){
for(j=0;j<temp.size();j++){
q.push(temp[j]);
}
temp.clear();
}
}
sort(a,a+n,cmp_by_id);
for(i=0;i<n;i++){
cout<<a[i].res<<" ";
}
}
身份证
解法一
知识点:排序、二分
思路:可以发现每个数都在 的数据范围内。对于一个十八位数
而言,
和它前
个数字相等意味着除了前
个数字以外,
的后
个数字一定在 000..00到 999..99范围内。
例如,对于数字123451234512345123,如果另一个数和它有长度为5的公共前缀,那么这个数的取值范围是 123450000000000000到123459999999999999。
所以这道题可以用二分来解,对于每个数,二分去找其前缀长度为 的合法上界和下界,若该上界和下界中包含的数不为零,那么意味着存在该公共前缀的数。
复杂度
解法二
知识点:字典树
思路:如果熟悉字典树的话可以发现这是一道字典树的裸题。建一棵字典树,每个节点上存该前缀的字符串数量。然后就可以做到每次 进行查询了。
复杂度
参考代码(二分解法):
#include<bits/stdc++.h>
using namespace std;
#define ll long long
vector<long long>v;
ll pow10[20];
int main(){
int n,q,i;
pow10[0]=1;
for(i=1;i<18;i++)pow10[i]=pow10[i-1]*10;
cin>>n>>q;
for(i=0;i<n;i++){
ll x;
cin>>x;
v.push_back(x);
}
sort(v.begin(),v.end());
while(q--){
ll x;
cin>>x;
ll j=17;
ll out1=0,out2=0;
for(i=1;i<=18;i++,j--){
ll l=x/pow10[j]*pow10[j],r=(x/pow10[j]+1)*pow10[j];
ll c1=lower_bound(v.begin(),v.end(),l)-v.begin();
ll c2=upper_bound(v.begin(),v.end(),r)-v.begin();
if(c1==c2)break;
out1=i,out2=c2-c1;
}
if(out1==0)out2=n;
cout<<out1<<" "<<out2<<endl;
}
}
腾讯成长空间 5873人发布

