C++小白训练第四天
C++小白训练第四天
以下为牛客挑战
今日收获
学习到两种遍历的方法
for (auto &z : a) z 是引用(别名) ✅ 修改会写回原数组
for (auto z : a) z 是值拷贝 ❌ 修改只影响副本
在函数内部定义函数要调用自己时候直接self(self),
auto inner = [&](int x) -> void { // & 表示按引用捕获外部所有变量
cout << x << endl;
};
字典树模板
const int N = 1e6 + 10; // 总结点上限,按需调大
int son[N][26], idx = 0; // son[p][c] 节点 p 的 c 号孩子;-1 表示空
bool isEnd[N]; // isEnd[p] 节点 p 是否是某个单词的结尾
void insert(const string &s) {
int p = 0; // 0 号节点是根
for (auto &ch : s) {
int u = ch - 'a'; // 0~25
if (!son[p][u]) son[p][u] = ++idx; // 没有路就修一条
p = son[p][u]; // 往下走
}
isEnd[p] = true; // 标记单词结束
}
牛客周赛 Round 126
小红的好数组构造

6 2
1 1 4 5 1 4
这个我们可以想到一个条件就是,n-k的结果必须是偶数,因为这个是必要条件,如果不满足就不能构造成功,因为好数组需要满足去除完后是偶数。
对于其他的我们可以这样构造,前面n-k个是1,后面的就是2,3,4,5,6排下去就行了。
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,k;
cin>>n>>k;
if((n-k)%2!=0){
cout<<"-1"<<endl;
}else{
for(int i=0;i<n-k;i++){
cout<<"1 ";
}
int m=1;
for(int i=n-k;i<n;i++){
cout<<++m<<" ";
}
}
return 0;
}
小红的左看右看构造

2 3 4
1 5
1 4 5
1 5 4 1
这个题画一个图就最好理解了

如果最后的数不相同直接-1.
就是如果两个数组的长度加起来没有,那么长,直接在中间补齐最大值就行
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,x,y;
cin>>x>>y>>n;
vector<int>a(x),b(y);
for (int i = 0; i < x; ++i) {
cin>>a[i];
}
for (int i = 0; i < y; ++i) {
cin>>b[i];
}
if(a.back()!=b.back()){
cout<<"-1";
return 0;
}
b.pop_back();//删除最后一个元素。
reverse(b.begin(),b.end());
while (a.size()+b.size()<n){
a.emplace_back(a.back());
}
if(a.size()+b.size()>n){
cout<<"-1";
return 0;
}
for(auto &z: a){
cout<<z<<" ";
}
for(auto &t: b){
cout<<t<<" ";
}
return 0;
}
小红的完全平方数构造

1
114514
11451412335057984
这个题比较不容易去思考
我们可以枚举长度

int l=n*(int)pow(10,i);
int r=n*(int)pow(10,i)+(int)pow(10,i)-1;
int m=sqrt(r);
if(m*m>=l){
cout<<m*m<<endl;
break;
}
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
void solve(){
int n;
cin>>n;
for(int i=1;i<=18;i++){
int l=n*(int)pow(10,i);
int r=n*(int)pow(10,i)+(int)pow(10,i)-1;
int m=sqrt(r);
if(m*m>=l){
cout<<m*m<<endl;
break;
}
}
};
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
TESTS{
solve();
};
return 0;
}
小红的基环树染色构造
二分树涂色

4
1 2
2 3
3 1
3 4
1 2 3 1
基环树:对于一个包含 n 个点的简单连通图,如果其包含 n 条边,那么我们便称他为一个基环树。
这个相当于比树多了一条边
我们可以当成树的特殊情况来做。

我们可以先把所有的按找两个颜色去图,因为这个是基环树,如果存在不满珠直接换成第3种方式。
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
vector<vector<int>>g(n+1);//图
vector<pair<int,int>>e(n);
for(int i=0,u,v;i<n;i++){
cin>>u>>v;
g[u].emplace_back(v);
g[v].emplace_back(u);
e[i]={u,v};//存边。
}
vector<int>ans(n+1);
auto dfs=[&](auto && self,int u,int op)->void {
ans[u]=op;
for(auto & v : g[u]){
if(ans[v]>0)continue;
self(self,v,3-op);
}
};
dfs(dfs,1,1);
for(auto & [u,v] : e){
if(ans[u]==ans[v]){
ans[u]=3;
}
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
return 0;
}
小红的字符串构造(hard)
字典树trie
G-小红的字符串构造(hard)_牛客周赛 Round 126


5 3
10
010
10101
1010
01
10101
这个是字典树,这个串就是那个字符串,01串就搞2个
这个是字符集的
const int N = 1e6 + 10; // 总结点上限,按需调大
int son[N][26], idx = 0; // son[p][c] 节点 p 的 c 号孩子;-1 表示空
bool isEnd[N]; // isEnd[p] 节点 p 是否是某个单词的结尾
void insert(const string &s) {
int p = 0; // 0 号节点是根
for (auto &ch : s) {
int u = ch - 'a'; // 0~25
if (!son[p][u]) son[p][u] = ++idx; // 没有路就修一条
p = son[p][u]; // 往下走
}
isEnd[p] = true; // 标记单词结束
}
vector<array<int,2>>tre(m+2);
vector<int>edg(m+1);
void insert(const string &str) {
int p = 0;
for (char ch : str) {
int u = ch - '0';
if (!tre[p][u]) tre[p][u] = ++index;
p = tre[p][u];
}
edg[p]++; // 这个节点是几个串的结尾
}
最后再进行dfs
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,k;
cin>>n>>k;
int m=0;
vector<string>s(n);
for(int i=0;i<n;i++){
cin>>s[i];
m+=s[i].size();
}
vector<array<int,2>>tre(m+2);
vector<int>edg(m+1);
int index=0;
auto insert=[&](string s)->void{
int p=0;
for(auto & c:s){
int u=c-'0';
if(!tre[p][u])tre[p][u]=++index;
p=tre[p][u];
}
edg[p]++;//终点。
};
for(int i=0;i<n;i++){
insert(s[i]);
}
string ans;
int sum=0;
bool ok=0;
auto dfs=[&](auto & self,int cur)->void {
if(ok)return ;
if(sum==k){
ok=1;
cout<<ans<<endl;
return;
}else if(sum>k){
return;
}
if(tre[cur][0]){
ans+='0';
sum+=edg[tre[cur][0]];
self(self,tre[cur][0]);
ans.pop_back();
sum-=edg[tre[cur][0]];
}
if(tre[cur][1]){
ans+='1';
sum+=edg[tre[cur][1]];
self(self,tre[cur][1]);
ans.pop_back();
sum-=edg[tre[cur][1]];
}
};
dfs(dfs,0);
if(!ok){
cout<<"-1"<<endl;
}
return 0;
}

浙公网安备 33010602011771号