A. Permutation Forgery
开始看错题了,导致傻逼题想了挺久的。。
#include <bits/stdc++.h>
using namespace std;
int a[205];
int main(){
ios::sync_with_stdio(false);
int t;cin>>t;
while(t--){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=n;i>=1;i--)cout<<a[i]<<' ';
cout<<endl;
}
}
B. Array Cancellation
题意:给你一个和为0的数组,每次可以选择两个不同的数 a i a_i ai 和 a j a_j aj,使 a i a_i ai 减1,使 a j a_j aj 加1,如果i<j,操作免费,否则代价为1,求最小代价
从前往后贪心,遇到正数存起来,遇到负数如果之前有正数就消掉他。实际可以发现这是在求一个最大后缀和,这里上比赛的代码。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100005];
int main(){
ios::sync_with_stdio(false);
int t;cin>>t;
while(t--){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
ll sum=0,ans=0;
for(int i=1;i<=n;i++){
if(a[i]>0)sum+=a[i];
else{
if(llabs(a[i])>sum){
a[i]+=sum;
sum=0;
}
else{
sum+=a[i];
a[i]=0;
}
}
}
for(int i=1;i<=n;i++){
if(a[i]<0)ans-=a[i];
}
cout<<ans<<endl;
}
}
C. Balanced Bitstring
题意:给你一个字符串,可以将字符串中的问号变成0或1,问你是否能使字符串的每连续k段里的0和1数量保持相同。
比如k=4第一段以0为首字符串
s
1
s_1
s1占据了0123四个位置,第二段以1为首的字符串
s
2
s_2
s2则占据了1234四个位置,由此可见两个字符串共享了123三个字符,为了使这两段字符串中的0和1的数量保持相同,位置0的字符必须和位置4的字符一样,由此推出结论
t
i
t_i
ti=
t
j
t_j
tj if i
≡
\equiv
≡ j (mod k) 即同余位置的字符相同
那我们只要检查0到k-1位的字符有多少0多少1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char s[300005];
int main(){
ios::sync_with_stdio(false);
int t;cin>>t;
while(t--){
int n,k;cin>>n>>k>>s;
int ok=0;
for(int i=0;i<k;i++){
char kk=s[i];
int flag=0;
for(int j=i+k;j<n;j+=k){
if(s[j]=='?')continue;
if(kk=='?'&&s[j]!='?'){//该同余位置必须为s[j]
kk=s[j];
s[i]=s[j];
continue;
}
if(kk!='?'&&s[j]!=s[i]){//该同余位置发生冲突,跳出
flag=1;
break;
}
}
if(flag){
ok=1;
break;
}
}
int a=0,b=0;
for(int i=0;i<k;i++){
if(s[i]=='0')a++;
else if(s[i]=='1')b++;
}
if(a>k/2||b>k/2)ok=1;
if(ok==0)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
D. Tree Tag
题意:在一棵顶点为n的树上,Alice和Bob开始位于两个不同的顶点,轮流移动,Alice先手。Alice可以移动到与当前顶点距离不超过da的顶点,Bob则不超过db,移动时允许停留在同一个顶点上,执行移动时仅占据开始顶点和结束的顶点,如果无限步内Alice和Bob占据了同一个顶点,Alice胜,否则Bob胜,求胜者。
样例给的很友善,基本容易wa的点都给了
- 如果他们的距离不超过da,那么Alice第一步就可以获胜,因此一个dfs求两点距离特判一下
- 如果2*da大于等于树的最长链,那么Alice只要占据树的中心,从而一步到达任意顶点取得胜利,因此两个dfs计算最长链长度
- db小于等于2*da,Alice获胜。比如此时Alice的Bob的距离为da+1,Alice向Bob移动一个顶点,使距离为da,此时Bob并不能移动到另一个子树,使自己不被抓到。
写了3个dfs。。
实际上计算最长链长度的第一个dfs可以把特判距离的dfs也顺便做了,所以只需要两次dfs
#include <bits/stdc++.h>
using namespace std;
const int N=200005;
struct node{
int to,next;
}edge[N];
int cnt=1,head[N],vis[N],maxs,maxi,ans;
inline void add(int u,int v){
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void init(int n){
cnt=1;
for(int i=1;i<=n*2;i++){
head[i]=0;
vis[i]=0;
}
}
void dfs(int x,int fa,int sum){
vis[x]=1;
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(vis[to]||to==fa)continue;
vis[to]=1;
dfs(to,x,sum+1);
}
if(sum>maxs){
maxs=sum;
maxi=x;
}
}
void solve(int x,int fa,int ends,int sum){
vis[x]=1;
for(int i=head[x];i;i=edge[i].next){
if(ans!=0)return;
int to=edge[i].to;
if(vis[to]||to==fa)continue;
if(to==ends){
ans=sum+1;
return;
}
vis[to]=1;
solve(to,x,ends,sum+1);
}
}
int main(){
ios::sync_with_stdio(false);
int t;cin>>t;
while(t--){
int n,a,b,da,db;
cin>>n>>a>>b>>da>>db;
init(n);
for(int i=1;i<=n-1;i++){
int u,v;cin>>u>>v;
add(u,v);add(v,u);
}
ans=0;//存距离
solve(a,-1,b,0);//求Alice和Bob的距离
if(ans<=da){//特判Alice的第一步是否能取胜
cout<<"Alice"<<endl;
continue;
}
for(int i=1;i<=n;i++)vis[i]=0;
maxs=0;
dfs(1,-1,0);//求最长链的一个顶点
for(int i=1;i<=n;i++)vis[i]=0;
maxs=0;//存长度
dfs(maxi,-1,1);//求最长链长度
if(da<maxs/2&&db>da*2)cout<<"Bob"<<endl;
else cout<<"Alice"<<endl;
}
}