A
#include <iostream>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 110;
int a[N];
int main()
{
SIS;
int t,n;
cin >> t;
while(t--){
cin >> n;
for(int i=1;i<=n;++i){
cin >> a[i];
}
int ans = a[1];
for(int i=2;i<=n;++i){
ans&=a[i];
}
cout << ans << '\n';
}
return 0;
}
B
#include <iostream>
#include <cstring>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 110;
char a[N];
int main()
{
SIS;
int t,n;
cin >> t;
while(t--){
memset(a,0,sizeof(a));
cin >> n;
cin >> (a+1);
bool flag = false;
for(int i=1;i<=n;++i){
if(a[i] != '?'){
flag = true;
break;
}
}
//全是问号
if(!flag){
a[1] = 'R';
for(int i=2;i<=n;++i){
if(a[i-1] == 'R') a[i] = 'B';
else a[i] = 'R';
}
}else{
for(int i=1;i<=n;++i){
if(a[i] == '?') continue;
int l = i-1,r=i+1;
while(a[l] == '?' && l>=1){
if(a[l+1] == 'R') a[l] = 'B';
else a[l] = 'R';
--l;
}
while(a[r] == '?' && r<=n){
if(a[r-1] == 'R') a[r] = 'B';
else a[r] = 'R';
++r;
}
}
}
cout << (a+1) << '\n';
}
return 0;
}
C
感觉C比D1难
#include <iostream>
#include <cstring>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 1e4+10;
int a[N],t,n;
void solve(){
if(a[1] == 1){
//n+1 -> 1
//n+1->1->2->3->...->n
cout << n+1 << ' ';
for(int i=1;i<=n;++i) cout << i << ' ';
cout <<'\n';
return;
}
if(a[n] == 0){
//n -> n+1
for(int i=1;i<=n+1;++i) cout << i <<' ';
cout << '\n';
return;
}
//都不是
for(int i=n-1;i>=1;--i){
if(a[i] == 0){
//i -> n+1
//1->2->..->i->n+1->i+1->..->n
for(int j=1;j<=i;++j){
cout << j << ' ';
}
cout << n+1 << ' ';
for(int j=i+1;j<=n;++j) cout << j << ' ';
cout << '\n';
return;
}
}
}
int main()
{
SIS;
cin >> t;
while(t--){
cin >> n;
for(int i=1;i<=n;++i) cin >> a[i];
solve();
}
return 0;
}
D1
暴力枚举点,然后并查集就行了
#include <iostream>
#include <cstring>
#include <vector>
#include <utility>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 1e3+10;
int f[N],g[N],t,n,m1,m2;
int ffind(int x){
if(x == f[x]) return x;
return f[x] = ffind(f[x]);
}
int gfind(int x){
if(x == g[x]) return x;
return g[x] = gfind(g[x]);
}
void solve(){
}
vector<pair<int,int>> ve;
int main()
{
SIS;
int ansc = 0;
cin >> n >> m1 >> m2;
for(int i=1;i<=n;++i) f[i] = g[i] = i;
for(int i=1,u,v;i<=m1;++i){
cin >> u >> v;
f[ffind(u)] = ffind(v);
}
for(int i=1,u,v;i<=m2;++i){
cin >> u >> v;
g[gfind(u)] = gfind(v);
}
for(int i=1;i<n;++i){
for(int j=i+1;j<=n;++j){
//是否能添加<i,j>
if(ffind(i) != ffind(j) && gfind(i)!=gfind(j)){
f[ffind(i)] = ffind(j);
g[gfind(i)] = gfind(j);
++ansc;
ve.push_back({i,j});
}
}
}
cout << ansc << '\n';
for(auto x : ve){
cout << x.first << ' ' << x.second << '\n';
}
return 0;
}
D2
官方题解好像是启发式合并
但是看不懂,然后到处翻博客;
以下为参考资料
跟D1的差距就是n变大了
因为D1是暴力枚举,其实有很多边是不需要去枚举的;
为了降低复杂度,我们希望只去连有用的边;
我们假设一号节点为主树,对于左右两森林都如此;
首先,如果对于点 i i i来说,既可以和左森林主树相连,又可以与右森林的主树相连,那么我们直接连接;
对于有些点我们是没有连的,但是是可以连的;
- 和左主树连会形成环,但是可以和右主树连
- 和右主树连会形成环,但是可以和左主树连
那么我们将这些点记录下来,让他们两两相连,同时判断不会形成环即可;
举例
<1,2>在左树连了,但是右树没连;
<1,4>在右树连了,但是左树没连;
那么就连<2,4>是可以连的;
Code
#include <iostream>
#include <cstring>
#include <vector>
#include <utility>
#include <queue>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 1e5+10;
int f[N],g[N],t,n,m1,m2;
int ffind(int x){
if(x == f[x]) return x;
return f[x] = ffind(f[x]);
}
int gfind(int x){
if(x == g[x]) return x;
return g[x] = gfind(g[x]);
}
void fmerge(int x,int y){
int fx = ffind(x);
int fy = ffind(y);
f[fx] = fy;
}
void gmerge(int x,int y){
int gx = gfind(x);
int gy = gfind(y);
g[gx] = gy;
}
vector<pair<int,int>> ansv;
queue<int> q1,q2;
int main()
{
SIS;
cin >> n >> m1 >> m2;
for(int i=1;i<=n;++i) f[i] = g[i] = i;
for(int i=1,u,v;i<=m1;++i){
cin >> u >> v;
fmerge(u,v);
}
for(int i=1,u,v;i<=m2;++i){
cin >> u >> v;
gmerge(u,v);
}
for(int i=2;i<=n;++i){
if(ffind(1)!=ffind(i)&&gfind(1)!=gfind(i)){
//直接插入ans
//emplace_back相比push_back 会自动初始化 效率高
ansv.emplace_back(1,i);
fmerge(1,i);
gmerge(1,i);
continue;
}
//能到这 要么和左树的1在一起,要么和右树的1在一起
if(ffind(1)!=ffind(i)){
q1.push(i);
}
if(gfind(1)!=gfind(i)){
q2.push(i);
}
}
while(1){
while(!q1.empty()&&ffind(1)==ffind(q1.front())){
q1.pop();
}
while(!q2.empty()&&gfind(1)==gfind(q2.front())){
q2.pop();
}
if(q1.empty()||q2.empty()) break;
int h1 = q1.front(),h2 = q2.front();
ansv.emplace_back(h1,h2);
fmerge(h1,h2);
gmerge(h1,h2);
}
cout << ansv.size() << '\n';
for(auto x : ansv){
cout << x.first << ' ' << x.second << '\n';
}
return 0;
}