A
如果某个字母连续出现的次数是奇数,那么这个键一定是好的,遍历一遍即可。
#include<bits/stdc++.h>
using namespace std;
int main(){
int T;
cin>>T;
while(T--){
string s;
cin>>s;
set<char> ans;
int l=(int)s.length();
char c=s[0];
int now=1;
for(int i=1;i<l;i++){
if(s[i]==c){
now++;
}else{
if(now&1) ans.insert(c);
c=s[i];
now=1;
}
}
if(now&1) ans.insert(c);
for(char c:ans) cout<<c;
}
return 0;
}
B
如果没有字符串的长度为奇数并且 0 0 0和 1 1 1的个数都是奇数,答案即为 n − 1 n-1 n−1,否则即为 n n n。
#include<bits/stdc++.h>
using namespace std;
int main(){
int T;
cin>>T;
while(T--){
string s;
int n1,n0;
n1=n0=0;
int n;
cin>>n;
bool check=0;
for(int i=1;i<=n;i++){
cin>>s;
for(char c:s){
if(c=='1') n1++;
else n0++;
}
int len=(int)s.length();
if(len&1) check=1;
}
int ans=(!check&&(n0&1)&&(n1&1))?n-1:n;
cout<<ans<<endl;
}
return 0;
}
C
考虑进行的操作,唯一不变的是奇数和偶数各自的顺序,因此就分开放然后用类似于归并排序的方式贪心的选取即可。
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--){
string s;
cin>>s;
queue<char> od,ev;
for(char c:s){
if((c-'0')&1) od.push(c);
else ev.push(c);
}
while(!od.empty()||!ev.empty()){
if(od.empty()){
cout<<ev.FRONT();
ev.pop();
continue;
}
if(ev.empty()){
cout<<od.FRONT();
od.pop();
continue;
}
if(od.FRONT()>=ev.FRONT()){
cout<<ev.FRONT();
ev.pop();
}else{
cout<<od.FRONT();
od.pop();
}
}
cout<<endl;
}
return 0;
}
D
考虑二分答案,对于每个中位数
m
m
m,如果
m
≤
L
i
m \leq L_i
m≤Li,那么一定是在
m
m
m的左边,
如果
R
i
<
m
R_i < m
Ri<m,那么一定在
m
m
m右边,贪心的选取,剩余的先暂时归到右边,然后每次选
L
i
L_i
Li小的归到左边直到左右相等即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+100;
ll L[N],R[N],T,n,s;
bool Cmp(pair<ll,ll> a,pair<ll,ll> b){
return a.first<b.first;
}
bool Check(ll med){
ll need=0;
int cnt=0;
vector<ll> maybe;
for(int i=1;i<=n;i++){
if(L[i]>=med){
cnt++;
need+=L[i];
}
else if(R[i]<med){
need+=L[i];
}else{
need+=med;
maybe.push_back(L[i]);
cnt++;
}
}
if(cnt<(n+1)/2) return 0;
for(ll v:maybe){
if(cnt>(n+1)/2){
need+=(v-med);//还回去
cnt--;
}else break;
}
return need<=s;
}
ll Solve(ll L,ll R){
bool flag=0;
for(int i=1;i<=80;i++){
ll mid=(L+R)>>1;
if(Check(mid)){
L=mid;
flag=1;
}else R=mid;
}
if(flag){
return L;
}else return -1;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--){
vector<pair<ll,ll>> ps;
cin>>n>>s;
for(ll i=1;i<=n;i++){
cin>>L[i]>>R[i];
ps.push_back({L[i],R[i]});
}
sort(ps.begin(),ps.end(),Cmp);
for(int i=0;i<n;i++){
L[i+1]=ps[i].first;
R[i+1]=ps[i].second;
}
ll ans=Solve(0,(ll)1e18);
cout<<ans<<endl;
}
return 0;
}
E1&E2
考虑按照 m m m从大向小处理,假设从 [ i + 1 , n ] [i+1,n] [i+1,n]已经贿赂了 c n t cnt cnt人,那么最多在 [ 1 , i − 1 ] [1,i-1] [1,i−1]贿赂 i − 1 i-1 i−1人,此时最多有 i − 1 + c n t i-1+cnt i−1+cnt人,因此,如果 i − 1 + c n t < m i i-1+cnt<m_i i−1+cnt<mi,那么就要选择便宜的人贿赂使得第 i i i人满足条件。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
pair<int,int> a[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].first>>a[i].second;
}
sort(a+1,a+n+1);
long long ans=0;
int cnt=0;//[i+1,n]已经收买了cnt人
priority_queue<int> q;
for(int i=n;i>=1;i--){//选出必须买的
q.push(-a[i].second);
int have=i-1;//假设前i-1全买了
while(have+cnt<a[i].first){
ans-=q.top();
q.pop();
cnt++;
}
}
cout<<ans<<endl;
}
return 0;
}