A
思路
记录每个字母的出现次数,然后扫一遍字母表判断即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
ll n;
ll t[40];
string s;
void print()
{
rep(i,1,26)
cout<<t[i]<<" ";
cout<<endl;
}
int main()
{
In(1,&n);
while(n--)
{
cin>>s;
memset(t,0,sizeof(t));
ll len=(ll)s.size();
s=' '+s;
rep(i,1,len)
{
t[s[i]-'a'+1]++;
}
ll flag=0,is=0,cnt=0;
rep(i,1,26)
{
if(t[i]>1)
{
flag=1;
break;
}
if(t[i])
{
is=1;
++cnt;
continue;
}
if(is && !t[i])
break;
}
if(cnt!=len || flag)
puts("No");
else
puts("Yes");
}
}
B
思路
把原数组的元素根据奇偶性分成两组,如果奇数和偶数的个数(分别记为)相差小于,就可以全部删完,答案为,否则就从较多的一组中取个数字作为答案。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E3+10;
ll n,ans,cnta,cntb;
ll a[N],b[N];
int main()
{
In(1,&n);
rep(i,1,n)
{
ll tmp;
In(1,&tmp);
if(tmp%2)
a[++cnta]=tmp;
else
b[++cntb]=tmp;
}
sort(a+1,a+cnta+1);
sort(b+1,b+cntb+1);
if(cnta>cntb)
{
ll cnt=cnta-cntb-1;
rep(i,1,cnt)
ans+=a[i];
}
else
{
ll cnt=cntb-cnta-1;
rep(i,1,cnt)
ans+=b[i];
}
cout<<ans<<endl;
}
C
思路
因为可以随便取来构造单调上升序列和单调下降序列,所以先从小到大排序,扫一遍数组,判断可以加到那个序列中即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll n,cnta,cntb;
ll a[N],x[N],y[N];
int main()
{
In(1,&n);
rep(i,1,n)
In(1,&a[i]);
sort(a+1,a+n+1);
x[0]=y[0]=LLm;
rep(i,1,n)
{
if(x[cnta]!=a[i])
x[++cnta]=a[i];
else if(y[cntb]!=a[i])
y[++cntb]=a[i];
else
{
cout<<"NO"<<endl;
return 0;
}
}
sort(y+1,y+cntb+1,greater<ll>());
puts("YES");
Out(1,cnta);
rep(i,1,cnta)
Out_(1,x[i]);
cout<<endl;
Out(1,cntb);
rep(i,1,cntb)
Out_(1,y[i]);
}
D
思路
最终得到的相等元素必定是原数组中出现过的,也就是说原先出现过的这些元素都不变,其他元素各自进行次操作。所以最优解必然是找出原数组中出现过最多的元素(记为,记出现次数为,则总的操作次数为。然后从每个开始向前扩散,最后一个还要向后扩散。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll n,num,maxi=LLm;
ll a[N],vis[N];
int main()
{
In(1,&n);
rep(i,1,n)
{
In(1,&a[i]);
++vis[a[i]];
if(vis[a[i]]>maxi)
{
maxi=vis[a[i]];
num=a[i];
}
}
Out(1,n-vis[num]);
rep(i,1,n)
{
if(a[i]==num)
{
for(int j=i-1;j>=1 && a[j]!=num;--j)
{
if(a[j]<num)
printf("1 %d %d",j,j+1);
else
printf("2 %d %d",j,j+1);
puts("");
}
}
}
for(int i=n;i>=1;--i)
{
if(a[i]==num)
{
rep(j,i+1,n)
{
if(a[j]<num)
printf("1 %d %d",j,j-1);
else
printf("2 %d %d",j,j-1);
puts("");
}
break;
}
}
}
E
思路
实际上就是进制的加法和除法,模拟高精度即可。十进制是遇进位,进制就是遇进位,因此分别对应。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll n,add,mul;
ll x[N],y[N];
string a,b;
void print()
{
rep(i,1,n)
cout<<(char)(x[i]+'a');
puts("");
}
int main()
{
In(1,&n);
cin>>a>>b;
rep(i,0,n-1)
{
x[i+1]=a[i]-'a';
y[i+1]=b[i]-'a';
}
for(int i=n;i>=1;--i)
{
x[i]+=y[i]+add;
add=x[i]>25?1:0;
if(i!=1)
x[i]%=26;
}
rep(i,1,n)
{
y[i]=(x[i]+mul)>>1;
mul=x[i]%2?26:0;
}
rep(i,1,n)
cout<<(char)('a'+y[i]);
}
F
思路
不能有长度超过的路,也就是说所有的点要么只有入度,要么只有出度。据此把所有的点分为两类,两个同类的点不可以连在一起,本题就转化为图上的染色问题,随便选个点即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll n,m,tot;
ll head[N],cl[N];
queue<ll> q;
char s[N];
struct Edge{
ll nxt,to;
}e[2*N];
struct edge{
ll frm,to;
}ed[2*N];
inline void add_edge(ll u,ll v,int flag)
{
e[++tot].nxt=head[u];
e[tot].to=v;
head[u]=tot;
if(flag)
add_edge(v,u,0);
}
void print()
{
rep(i,1,n)
Out_(1,cl[i]);
}
int main()
{
cin>>n>>m;
rep(i,0,m)
s[i]='0';
rep(i,1,m)
{
ll u,v;
scanf("%lld %lld",&u,&v);
add_edge(u,v,1);
ed[i]=(edge){u,v};
}
q.push(1);
rep(i,1,n)
cl[i]=-1;
cl[1]=1;
while(q.size())
{
ll u=q.front();
q.pop();
bl(u,i)
{
ll v=e[i].to;
if(cl[v]!=-1)
{
if(cl[v]==cl[u])
{
puts("NO");
return 0;
}
continue;
}
cl[v]=cl[u]^1;
q.push(v);
}
}
rep(i,1,m)
{
ll frm=ed[i].frm;
if(cl[frm])
s[i]='1';
}
puts("YES");
rep(i,1,m)
cout<<s[i];
puts("");
}
G
思路
本题和C题的区别就在于元素是要按顺序选的。记当前得到的单调上升序列的末尾元素为,单调下降序列的末尾元素为,对原数组中的元素分类讨论:
- 若,无解。
- 若,那么只能加入单调上升序列。
- 若,那么只能加入单调下降序列。
- 若,那就要看与的大小关系。若,那么将加入单调上升序列显然是更优的,因为这样就可以保证单调上升序列的末尾元素尽可能小,单调下降序列的末尾元素尽可能大。否则就把加入单调下降序列。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll n;
ll a[N],ans[N];
int main()
{
In(1,&n);
rep(i,1,n)
In(1,&a[i]);
ll maxi=LLm,mini=LLM;
rep(i,1,n)
{
if(a[i]<=maxi && a[i]>=mini)
{
puts("NO");
return 0;
}
if(a[i]>maxi && a[i]>=mini)
maxi=a[i];
else if(a[i]<mini && a[i]<=maxi)
{
mini=a[i];
ans[i]=1;
}
else if(a[i]>maxi && a[i]<mini)
{
if(a[i+1]>a[i])
maxi=a[i];
else
{
mini=a[i];
ans[i]=1;
}
}
}
puts("YES");
rep(i,1,n)
Out_(1,ans[i]);
}