A. Permutation Forgery
因为只要排完序一样,所以逆序输出即可。
#include <iostream>
#include <stdio.h>
using namespace std;
int T,n;
int a[105];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int i=n;i>=1;i--)
printf("%d ",a[i]);
puts("");
}
return 0;
}
B. Array Cancellation
只有正数在前,负数在后,才可无消耗改变。所以,我们遇到正数,将其加入集合,然后遇到负数,就与之前加入集合的正数消耗。如果正数被消耗完,负数还在,那就加上负数的相反数。最后加上集合中的正数。然后除2即可(因为消耗1可以改变2个)。
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn=1e5+5;
int T,n;
int a[maxn];
int b[maxn];
int cnt;
int main()
{
scanf("%d",&T);
while(T--)
{
long long ans=0;
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int i=1;i<=n;++i)
{
if(a[i]>0)
{
b[++cnt]=a[i];
}
else
if(a[i]<0)
{
while(cnt)
{
if(b[cnt]>=-a[i])
{
b[cnt]+=a[i];
a[i]=0;
if(!b[cnt])
cnt--;
break;
}
else
{
a[i]+=b[cnt];
cnt--;
}
}
if(a[i]!=0)
ans-=(long long)a[i];
}
//cout<<ans<<endl;
}
while(cnt)
{
ans+=(long long)b[cnt];
cnt--;
}
printf("%lld\n",ans/2);
}
return 0;
}
C. Balanced Bitstring
很好的思维题,我们发现,当向后遍历时,只要前面少的那个与后面多的那个一样,就满足条件。因此,只要a[i]与a[i%k]一样,并且前k个满足条件,之后就一定满足。所以我们保证a[i]与a[i%k]相等,如果a[i]等于?,既可以当1,也可以当0。最后,判断一下前k个是否满足条件即可。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=3e5+5;
int T,n,k;
char a[maxn];
int b[3];
int main()
{
scanf("%d",&T);
while(T--)
{
b[0]=b[1]=b[2]=0;
scanf("%d%d",&n,&k);
scanf("%s",a);
int flag=0;
int t=k>>1;
for(int i=k;a[i];++i)
{
if(a[i]==a[i%k]||a[i]=='?')
continue;
if(a[i%k]=='?')
a[i%k]=a[i];
else
{
flag=1;
break;
}
}
if(flag)
{
puts("NO");
continue;
}
for(int i=0;i<k;++i)
{
if(a[i]!='?')
b[a[i]-'0']++;
}
if(b[0]>t||b[1]>t)
flag=1;
if(flag)
puts("NO");
else
puts("YES");
}
return 0;
}
D. Tree Tag
树上博弈,我们发现,如果 2da>=db,那么就一定可以追到。如果 2da>=树的直径,那么也一定可以追到。如果起初Alice在a点可在da内到达b,那么也可以追到。如果都不满足,Alice必定追不到,因为只要靠近Bob在da内,Bob就可以和他拉开至少da+1,这样便永远追不到。
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn=1e5+5;
struct node
{
int to,next;
}edge[maxn<<1];
int head[maxn];
int T,n,a,b,da,db,cnt,dist;
int dp1[maxn],dp2[maxn];
int depth[maxn];
void add(int x,int y)
{
edge[++cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt;
}
void dfs(int u,int fa)
{
dp1[u]=dp2[u]=0;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa)
continue;
dfs(v,u);
if(dp1[u]<dp1[v]+1)
{
dp2[u]=dp1[u];
dp1[u]=dp1[v]+1;
}
else
if(dp1[v]+1>dp2[u])
{
dp2[u]=dp1[v]+1;
}
}
}
void dis(int u,int fa)
{
depth[u]=depth[fa]+1;
if(u==b)
{
dist=depth[u]-1;
return;
}
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa)
continue;
dis(v,u);
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
cnt=0;
scanf("%d%d%d%d%d",&n,&a,&b,&da,&db);
for(int i=1;i<=n;++i)
head[i]=0;
for(int i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
if(2*da>=db)
{
puts("Alice");
continue;
}
dfs(1,0);
int ma=0;
for(int i=1;i<=n;++i)
ma=max(ma,dp1[i]+dp2[i]);
if(ma<=2*da)
{
puts("Alice");
continue;
}
dis(a,0);
if(dist<=da)
{
puts("Alice");
}
else
{
puts("Bob");
}
}
return 0;
}