前四个题就A题难想一点,别的读懂题就可以写出来。
结果这题卡我一个多小时
A. Mocha and Math
题意:给你一个序列,你可以对称的把区间里的
a
i
a_i
ai替换成
a
i
+
l
a_{i+l}
ai+l &
a
r
−
i
a_{r-i}
ar−i,如上图。问你操作若干次之后序列中的最小值。
思路:首先了解&的性质,
A
A
A &
B
<
=
m
i
n
(
A
,
B
)
B<=min(A,B)
B<=min(A,B),所以随着&操作的增加,值肯定是不断减少的,对于序列的某一个元素来说,它可以选择无数个区间使得
a
i
a_i
ai被替换成
a
1
a_1
a1&
a
2
a_2
a2&
a
3
a_3
a3&
.
.
.
.
.
.....
.....&
a
n
a_n
an,根据性质,此时的
a
i
a_i
ai已经达到了潜力上的最小值,此时无论再与谁&运算也不会更小了,所以我们干脆把所有的数都&一遍,最小的那个元素的贡献一定在其中,因为本身&也有类似取最小值的性质。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int mod = 1e9+7;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 1e5+10;
int a[N];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
LL res=a[1];
for(int i=1;i<=n;i++)
{
res=res&a[i];
}
cout<<res<<endl;
}
}
B - Mocha and Red and Blue
直接找到第一个非 ‘?’ ,遍历其左右。
显然只要保证与之前存在的字符不同,就可以贪心的得到最优解。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
string st;
cin>>st;
int k=-1;
int flag=0;
for(int i=0;i<n;i++)
{
if(st[i]!='?'&&k==-1)
{
k=i;
}
if(st[i]=='?') flag++;
}
if(flag==n)
{
for(int i=1;i<=n;i++)
{
if(i%2) cout<<'B';
else cout<<'R';
}
puts("");
continue;
}
if(k==-1) {cout<<st<<endl;continue;}
else
{
for(int i=k;i>=1;i--)
{
if(st[i]=='R'&&st[i-1]=='?') st[i-1]='B';
else if(st[i]=='B'&&st[i-1]=='?') st[i-1]='R';
}
for(int i=k;i<=n-2;i++)
{
if(st[i]=='R'&&st[i+1]=='?') st[i+1]='B';
else if(st[i]=='B'&&st[i+1]=='?') st[i+1]='R';
}
}
cout<<st<<endl;
}
}
C - Mocha and Hiking
读懂题就行,判断一下最后一辆车能否到达终点。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int mod = 1e9+7;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 1e5+10;
int a[N];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(a[n]==0)
{
for(int i=1;i<=n+1;i++) cout<<i<<' ';
puts("");
}
else
{
int k=-1;
for(int i=n;i>=1;i--)
{
if(!a[i])
{
k=i;
break;
}
}
if(k==-1)
{
cout<<n+1<<" ";
for(int i=1;i<=n;i++) cout<<i<<" ";
cout<<endl;
}
else
{
for(int i=1;i<=k;i++) cout<<i<<' ';
cout<<n+1<<' ';
for(int i=k+1;i<=n;i++) cout<<i<<' ';
cout<<endl;
}
}
}
}
D1 - Mocha and Diana (Easy Version)
不 形 成 环 = 在 一 个 连 通 块 之 中 的 点 对 不 再 建 边 不形成环=在一个连通块之中的点对不再建边 不形成环=在一个连通块之中的点对不再建边
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define x first
#define y second
using namespace std;
const int mod = 1e9+7;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 1e5+10;
int p1[N];
int p2[N];
PII ans[N];
int find1(int x)
{
if(x==p1[x]) return x;
else return p1[x]=find1(p1[x]);
}
int find2(int x)
{
if(x==p2[x]) return x;
else return p2[x]=find2(p2[x]);
}
void merge(int x,int y)
{
int px=find1(x);
int py=find1(y);
p1[px]=py;
px=find2(x);
py=find2(y);
p2[px]=py;
}
int main()
{
int n,m1,m2;
cin>>n>>m1>>m2;
int a,b;
for(int i=1;i<=n;i++) p1[i]=i,p2[i]=i;
while(m1--)
{
cin>>a>>b;
if(find1(a)!=find1(b))
{
p1[find1(a)]=find1(b);
}
}
while(m2--)
{
cin>>a>>b;
if(find2(a)!=find2(b))
{
p2[find2(a)]=find2(b);
}
}
int ct=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(find1(i)!=find1(j)&&find2(i)!=find2(j))
{
ans[++ct]={i,j};
merge(i,j);
}
}
}
cout<<ct<<endl;
for(int i=1;i<=ct;i++) cout<<ans[i].x<<' '<<ans[i].y<<endl;
}