A. Red Versus Blue
题意:
红队和蓝队比赛,红队赢
r
r
r局,蓝队赢
b
b
b局
(
r
>
b
)
(r>b)
(r>b),由于比赛过程势均力敌,请你构造出合适的字符串使红队的最长连胜最小
思路:
考虑在蓝队的
b
b
b局共
b
+
1
b+1
b+1个空位均值插入
r
r
r即可
#include<bits/stdc++.h>
#define pb push_back
#define inf 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<int,int> PII;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,r,b;
scanf("%d%d%d",&n,&r,&b);
int num=r/(b+1);
int mod=r%(b+1);
for(int i=1;i<=b+1;i++)
{
for(int j=1;j<=num;j++) printf("R");
if(i<=mod) printf("R");
if(i!=(b+1))
printf("B");
}
puts("");
}
}
B. Bit Flipping
题意:
给你一串长度
n
n
n的
01
01
01串,以及
k
k
k次操作,每次操作会使除了选定的位置不变,其余的位置均翻转,求
k
k
k次操作后可以得到的字典序最大的串以及
n
n
n个点上每个点的操作次数
思路:
从高位向低位贪心,若对某个位置进行了
p
p
p次操作,则意味着该位置会翻转
k
−
p
k-p
k−p次,根据奇偶关系尽可能使高位变为
1
1
1。若操作完前
n
−
1
n-1
n−1位后仍有剩余操作,则全部操作给第
n
n
n位
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
char s[maxn];
int a[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d%s",&n,&k,s+1);
for(int i=1;i<=n;i++) a[i]=0;
int num=k;
for(int i=1;i<n;i++)
{
if(num>0)
{
if(s[i]=='1')
{
if(k%2==0) continue;
else a[i]++,num--;
}
else
{
if(k%2==1)
{
s[i]='1';continue;
}
else a[i]++,num--,s[i]='1';
}
}
else
{
if(k%2)
{
if (s[i]=='1') s[i]='0';
else s[i]='1';
}
}
}
a[n]=num;
if(k%2)
{
if(num%2==0)
{
if(s[n]=='1') s[n]='0';
else s[n]='1';
}
}
else
{
if(num%2)
{
if(s[n]=='1') s[n]='0';
else s[n]='1';
}
}
printf("%s\n",s+1);
for(int i=1;i<=n;i++) printf("%d ",a[i]);
puts("");
}
}
C. Line Empire
题意:
你的王国在
0
0
0的位置上,首都位置为
c
a
p
=
0
cap=0
cap=0,此外在大于
0
0
0的位置
x
1
.
.
.
x
n
x_1...x_n
x1...xn上还有
n
n
n个王国,为了征服这
n
n
n个王国,你可以
- 占领一座王国,花费 b ∗ ∣ c a p − x ∣ b*\left|cap-x\right| b∗∣cap−x∣
- 将首都移到一个已经占领的王国,花费 a ∗ ∣ c a p − x ∣ a*\left|cap-x\right| a∗∣cap−x∣
求全部占领的最小花费
思路:
考虑最终的首都在
x
i
x_i
xi,迁都的总花费为
a
∗
∣
x
i
−
0
∣
a*\left|x_i-0\right|
a∗∣xi−0∣,等价于
a
∗
∣
x
i
−
x
i
−
1
∣
+
a
∗
∣
x
i
−
1
−
x
i
−
2
∣
.
.
.
a*|x_i-x_{i-1}|+a*|x_{i-1}-x_{i-2}|...
a∗∣xi−xi−1∣+a∗∣xi−1−xi−2∣...
即若首都最终在
x
i
x_i
xi,结果等价于将首都依次从
x
1
x_1
x1移动到
x
i
x_i
xi,于是只需要枚举首都最终的位置,就可以确定各个情况的操作过程,直接计算即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
ll x[maxn],sum[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll n,a,b;
scanf("%lld%lld%lld",&n,&a,&b);
for(int i=1;i<=n;i++)
{
scanf("%lld",&x[i]);
sum[i]=sum[i-1]+x[i];
}
ll ans=sum[n]*b,res=0;
for(int i=1;i<=n;i++)
{
res+=(a+b)*(x[i]-x[i-1]);
ll temp=res+b*(sum[n]-sum[i]-x[i]*(n-i));
ans=min(ans,temp);
}
printf("%lld\n",ans);
}
}
D. Reverse Sort Sum
题意:
给你长度为
n
n
n的
01
01
01数组
A
A
A,
f
(
k
,
A
)
f(k,A)
f(k,A)表示将
A
A
A中的前
k
k
k位按大小排序,返回为排好序的数组
B
B
B
数组
C
C
C为
f
(
1
,
A
)
+
f
(
2
,
A
)
+
.
.
.
+
f
(
n
,
A
)
f(1,A)+f(2,A)+...+f(n,A)
f(1,A)+f(2,A)+...+f(n,A)
告诉你数组
C
C
C,请为之构造合适的数组
A
A
A
思路:
将
C
C
C中所有元素相加,除以
n
n
n,得到
c
n
t
cnt
cnt为
A
A
A中数字
1
1
1出现的次数
考虑倒序思考,若在前
i
i
i位中有
c
n
t
cnt
cnt个
1
1
1,则可使
C
C
C上
[
i
−
c
n
t
+
1
,
i
]
[i-cnt+1,i]
[i−cnt+1,i]区间减一,操作完成后若
C
i
C_i
Ci依然大于
0
0
0,则说明
A
i
=
1
A_i=1
Ai=1,同时更新维护
c
n
t
cnt
cnt
#include<bits/stdc++.h>
#define lowbit(x) x&-x
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int c[maxn],a[maxn],add[maxn],n;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ll sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&c[i]);
sum+=c[i];a[i]=0;add[i]=0;
}
int cnt=sum/n,del=0;
for(int i=n;i>=1;i--)
{
if(cnt==0) break;
del--;
add[i-cnt]++;
del+=add[i];
if(c[i]+del>0) cnt--,a[i]=1;
}
if(cnt) a[1]=1;
for(int i=1;i<=n;i++) printf("%d ",a[i]);
puts("");
}
}
E. AND-MEX Walk
题意:
给你
n
n
n个点
m
m
m条边的无向连接图,点
u
u
u到
v
v
v的权值为
w
w
w。
从点
a
a
a到点
b
b
b所走路径上权值为
{
w
1
,
w
2
.
.
.
w
k
}
\{w_1,w_2...w_k\}
{w1,w2...wk},花费为
m
e
x
(
{
w
1
,
w
1
&
w
2
,
.
.
.
,
w
1
&
w
2
&
.
.
.
&
w
k
}
)
mex(\{w_1,w_1\&w_2,...,w_1\&w_2\&...\&w_k\})
mex({w1,w1&w2,...,w1&w2&...&wk})
接下来有
q
q
q次询问,每次回答从
a
a
a到
b
b
b的花费
思路:
对于答案,只可能是
0
,
1
,
2
0,1,2
0,1,2三种情况
将该无向图按照权值的二进制位分解为
30
30
30个子图,每一位的子图上只有权值在这一位上为
1
1
1才可以连接
- 若答案为 0 0 0,则要求有一位在该路径上始终出现,对 30 30 30个图使用并查集判断,看看是否在某一位的子图上 a a a和 b b b相连,则说明该位始终出现
- 若答案为 1 1 1,则说明不存在上述情况。对于除了第 0 0 0位的其他位上的子图,若从起点开始,可以到达一条偶数边,则说明第 0 0 0位上的 1 1 1已经被完全消除,随后可以在连通图上随意移动,都不可能会再出现 1 1 1
- 若上述两种情况均不可,则答案为 2 2 2
#include<bits/stdc++.h>
#define pb push_back
typedef long long ll;
using namespace std;
const int maxn=1e5+7;
int n,m,vis[maxn],ok[35][maxn];
vector<int>v[maxn];
struct DSU
{
int fa[maxn],p[maxn];
void init()
{
for(int i=1;i<=n;i++) fa[i]=i,p[i]=0;
}
int find(int x)
{
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
void connect(int x,int y)
{
int px=find(x),py=find(y);
fa[px]=py;
}
}g[35];
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<=30;i++) g[i].init();
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(c%2==0) vis[a]=1,vis[b]=1;
v[a].pb(b);v[b].pb(a);
for(int j=0;j<=30;j++)
{
if(c>>j&1)
{
g[j].connect(a,b);
}
}
}
for(int i=1;i<=n;i++)
{
if (vis[i])
{
for(int j=1;j<=30;j++)
{
ok[j][g[j].find(i)]=1;
}
}
}
int q;
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
int flag=0;
for(int i=0;i<=30;i++)
{
if(g[i].find(a)==g[i].find(b))
{
flag=1;break;
}
}
if(flag)
{
puts("0");continue;
}
for(int i=0;i<=30;i++)
{
if(ok[i][g[i].find(a)]) flag=1;
}
if(flag) puts("1");
else puts("2");
}
}