Codeforces Round #668 (Div. 2)(A B C D)
题目列表
- A - Permutation Forgery
- B - Array Cancellation
- C - Balanced Bitstring
- D - Tree Tag
Practice link:https://codeforces.ml/contest/1405
A - Permutation Forgery
思路:直接倒序输出即可。
代码:
int sum[105];
int a[105];
int b[105];
int n;
int main()
{
int TT;
cin>>TT;
while(TT--){
scanf("%d",&n);
int num;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=n;i>=1;i--){
printf("%d ",a[i]);
}
cout<<endl;
}
return 0;
}
B - Array Cancellation
思路:从1开始求和,求前i项和最小的数即可,最后输出这个数的绝对值。
代码:
ll a[100005];
int n;
int main()
{
int TT;
cin>>TT;
while(TT--){
scanf("%d",&n);
ll minn=0;
ll num=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
num+=a[i];
minn=min(num,minn);
}
printf("%lld\n",abs(minn));
}
return 0;
}
C - Balanced Bitstring
题意:有一个由01组成的字符串,其中有一些是?,问你是否有可能让这个串中所有长度为k的子串的01数量相等。
思路:由于是所有子串,很显然: s[i]=s[i+k]=s[i-k]
在这个条件下,可以把一些?的值确定下来,如果有s[i]!=s[i+k]或s[i]!=s[i-k],则直接输出no 。最后只需要判断s[1]~s[k]这个子串是否可以符合01数量相等即可。
代码:
char s[300005];
int n,k;
int main()
{
int TT;
cin>>TT;
while(TT--){
scanf("%d %d",&n,&k);
getchar();
for(int i=1;i<=n;i++){
scanf("%c",&s[i]);
}
int kk=1;
for(int i=1;i<=n-k;i++){
if(s[i]!=s[i+k]&&s[i]!='?'&&s[i+k]!='?'){
kk=0;
break;
}
if(s[i]!=s[i+k]){
if(s[i]=='?'){
s[i]=s[i+k];
}
if(s[i+k]=='?'){
s[i+k]=s[i];
}
}
}
if(kk){
for(int i=n;i>k;i--){
if(s[i]!=s[i-k]&&s[i]!='?'&&s[i-k]!='?'){
kk=0;
break;
}
if(s[i]!=s[i-k]){
if(s[i]=='?'){
s[i]=s[i-k];
}
if(s[i-k]=='?'){
s[i-k]=s[i];
}
}
}
}
if(!kk){
printf("NO\n");
}else{
int num=0,pp=0;
for(int i=1;i<=k;i++){
if(s[i]=='?'){
num++;
}else if(s[i]=='1'){
pp++;
}
}
int qq=k-pp-num;
if(num-abs(pp-qq)>=0&&(num-abs(pp-qq))%2==0){
kk=1;
}else{
kk=0;
}
if(kk){
printf("YES\n");
}else{
printf("NO\n");
}
}
}
return 0;
}
D - Tree Tag
题意:A和B分别在一棵树的不同节点上,A最多一步移动da个,B最多移动db格,在10^100步的范围内,如果A和B在同一格,则A获胜,否则B获胜。
思路:10^100很大,就是无限步,很显然,B只有在这棵树的最长路径上活动是最优的,也就是在树的直径上。首先,如果A和B两点的初始距离<=da,那么A可以一步抓住B。对于B最优的就是在直径的一端,当A靠近距离小于等于da时,就逃走,那么要逃到A不可以够到的范围,就最少要跳\(2\times da+1\),那么此时就要保证\(db>2\times da\),因为要跳那么多步,就要保证直径大于\(2\times da\)。
代码:
const int maxn=100010;
int n,a,b,da,db;
struct node{int v,dis,nxt;}E[maxn<<2];
int head[maxn],tot=0;
int dp[maxn],mxlen;
void init()
{
tot=0;
mxlen=0;
mem(head,0);
}
void add(int u,int v,int dis)
{
E[++tot].nxt=head[u];
E[tot].v=v; E[tot].dis=dis;
head[u]=tot;
}
void DP(int u,int pa)
{
dp[u]=0;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(v==pa) continue;
DP(v,u);
mxlen=max(mxlen,dp[u]+dp[v]+E[i].dis);
dp[u]=max(dp[u],dp[v]+E[i].dis);
}
}
int vis[maxn];
struct num{
int x,dd;
};
int bfs()
{
queue<num>q;
num s1;
s1.x=a;
s1.dd=0;
q.push(s1);
vis[a]=1;
while(!q.empty()){
num s2=q.front();
q.pop();
int u=s2.x;
vis[u]=1;
for(int i=head[u];i;i=E[i].nxt){
int v=E[i].v;
num s3;
s3.x=v;
s3.dd=s2.dd+1;
if(v==b){
return s3.dd;
}
if(vis[v]==1)continue;
q.push(s3);
}
}
return 0;
}
int main()
{
int TT;
cin>>TT;
while(TT--){
init();
mem(vis,0);
scanf("%d %d %d %d %d",&n,&a,&b,&da,&db);
for(int i=1;i<n;i++){
int u,v;
scanf("%d %d",&u,&v);
add(u,v,1);
add(v,u,1);
}
DP(1,0);
int dd=bfs();
if(dd>da&&2*da+1<=mxlen&&2*da+1<=db){
printf("Bob\n");
}else{
printf("Alice\n");
}
}
return 0;
}
总结
不足之处:对读题没有耐心。
容易紧张,想不到简单思路。
提高字符串方面的思维能力。
在考虑博弈问题时,要思考对某一方的最坏情况。
要提高从复杂的转化为已知或熟悉的能力。
越自律,越自由