我实在是太鸡了,天天gugugu不说,题也不会写,只能开始漫长的补题生活了。
A. Diverse Strings
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define mm(i,v) memset(i,v,sizeof i);
using namespace std;
typedef long long ll;
char str[1000000];
ll T,n;
int main()
{
ll i,j;
cin>>T;
while(T--)
{
cin>>str+1;
n=strlen(str+1);
sort(str+1,str+n+1);
for(i=1;i<n;i++) if(str[i]!=str[i+1]-1) break;
if(i<n) puts("No");
else puts("Yes");
}
}
B. Parity Alternated Deletions
大概就是删一次奇数,删一次偶数,求出最后剩下的数加起来的最小值。
直接模拟
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define mm(i,v) memset(i,v,sizeof i);
using namespace std;
typedef long long ll;
const int maxn=2000+10;
ll a[maxn],n;
vector<ll> odd,even;
ll ans;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
ans+=a[i];
if(a[i]&1)
odd.push_back(a[i]);
else
even.push_back(a[i]);
}
sort(odd.begin(),odd.end());
sort(even.begin(),even.end());
int so=odd.size()-1,se=even.size()-1,f=0;
cout<<so<<se<<endl;
if(odd.size()>even.size())
f=1;
while(1){
if(f==0){
if(se<0)
break;
ans-=even[se];
se--;
}
if(f==1){
if(so<0)
break;
ans-=odd[so];
so--;
}
f^=1;
}
cout<<ans<<"\n";
return 0;
}
C. Two Shuffled Sequences
给出一组数,先按升序输出一串,再按降序输出一串,保证每串都没重复的,而且一个数只能用一次。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define mm(i,v) memset(i,v,sizeof i);
using namespace std;
typedef long long ll;
const int maxn=200009;
int a[maxn],num[maxn];
vector<int> inc,decr;
int n;
int main(){
mm(num,0);
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
num[a[i]]++;
}
for(int i=0;i<=200000;i++){//不是很懂为什么这儿写maxn就错,疯狂卡我,交了无数次!
if(num[i] >= 3) {
cout<<"NO"<<endl;
return 0;
}
}
for(int i=0;i<=200000;i++){
if(num[i]>=2)
inc.push_back(i);
}
for(int i=200000;i>=0;i--){
if(num[i]>=1)
decr.push_back(i);
}
cout<<"YES\n";
cout<<(int)inc.size()<<"\n";
for(int i=0;i<inc.size();i++)
cout<<inc[i]<<(i==inc.size()-1? "\n":" ");
cout<<(int)decr.size()<<"\n";
for(int i=0;i<decr.size();i++)
cout<<decr[i]<<(i==decr.size()-1? "\n":" ");
return 0;
}
D. Equalize Them All
个人感觉这题是很的水。去个绝对值,再观察一下式子,就直接找到思路了。
简言之就是,找到出现最多的数,比它位置小而且小于他的数执行操作1,大于它的数执行操作2。比它位置大的数大于他就操作2,小于就操作1.
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define mm(i,v) memset(i,v,sizeof i);
using namespace std;
typedef long long ll;
const int maxn=200010;
int a[maxn],num[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,pos,t;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
num[a[i]]++;
}
int minn=n;
for(int i=0;i<200010;i++){
if(n-num[i]<minn){
minn=n-num[i];
pos=i;
}
}
cout<<minn<<"\n";
queue<int> q;
for(int i=1;i<=n;i++){
if(a[i]==pos)
q.push(i);
}
while(!q.empty()){
t=q.front();
q.pop();
if(t>1&&a[t-1]!=a[t]){
if(a[t-1]<a[t])
cout<<1<<" "<<t-1<<" "<<t<<"\n";
else
cout<<2<<" "<<t-1<<" "<<t<<"\n";
a[t-1]=a[t];
q.push(t-1);
}
if(t<n&&a[t+1]!=a[t]){
if(a[t+1]>a[t])
cout<<2<<" "<<t+1<<" "<<t<<"\n";
else
cout<<1<<" "<<t+1<<" "<<t<<"\n";
a[t+1]=a[t];
q.push(t+1);
}
}
return 0;
}
E. Median String
大概就是给了两串字符串,按字典序从第一个到第二个,让你输出中间的一个。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define mm(i,v) memset(i,v,sizeof i);
using namespace std;
typedef long long ll;
const int maxn=200000+10;
int n,a[maxn],b[maxn],c[maxn];
int cc=0;
string s,t;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>s>>t;
for(int i=0;i<n;i++)
a[i]=(s[i]-'a');
for(int i=0;i<n;i++)
b[i]=(t[i]-'a');
for(int i=0;i<n;i++){
c[i]=(a[i]+b[i])/2;
c[i]+=cc;
int temp=i;
while(c[temp]>=26){
c[temp]-=26;
c[temp-1]+=1;
temp--;
}
if((a[i]+b[i])%2==1)
cc=13;
else
cc=0;
}
for(int i=0;i<n;i++)
cout<<(char)('a'+c[i]);
cout<<"\n";
return 0;
}
F. Graph Without Long Directed Paths
题意 给你n个点 m条边 保证联通 问你能否构造一张有向图(不一定联通)使得路径长度不超过2
我们很容易想到从一个点开始染色 和他相连的点染相反颜色 然后再继续递归下去染色
但是要判断一下 这个点染色和下个点染色是否相反 如果那个点已经有颜色和自己是一样的 那么肯定是NO
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define mm(i,v) memset(i,v,sizeof i);
using namespace std;
typedef long long ll;
const int maxn=1<<18;
int u[maxn],v[maxn],col[maxn];
bool f=0;
vector<int> m[maxn];
void dfs(int cur,int dep){
if(col[cur]>=0){
if(col[cur]!=dep)
f=1;
return ;
}
col[cur]=dep;
for(int i=0;i<m[cur].size();i++){
dfs(m[cur][i],dep^1);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
mm(col,-1);
int n,mm;
cin>>n>>mm;
for(int i=1;i<=mm;i++){
cin>>v[i]>>u[i];
m[v[i]].push_back(u[i]);
m[u[i]].push_back(v[i]);
}
dfs(1,0);
if(f==1){
cout<<"NO\n";
return 0;
}
cout<<"YES\n";
for(int i=1;i<=mm;i++){
if(col[v[i]]==0)
cout<<1;
else
cout<<0;
}
return 0;
}