2022NOIP A层联测16
A. 平衡(balance)
打表找规律,发现一定是 交替, 因为是环,转回来的话必须是奇数,所以偶数无解
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 1000005;
int n, a[maxn];
void sol(){
n = read();
if((n & 1) == 0){
printf("NO\n");
return;
}
printf("YES\n");
a[1] = 1;
int p = 1;
for(int i = 1; i * 4 <= n + n; ++i){
a[++p] = i * 4;
if(i * 4 + 1 <= n + n)a[++p] = i * 4 + 1;
}
for(int i = 2; i <= n + n; ++i)if(i % 4 != 0 && i % 4 != 1)a[++p] = i;
for(int i = 1; i <= n + n; ++i)printf("%d ", a[i]);
}
int main(){
freopen("balance.in","r",stdin);
freopen("balance.out","w",stdout);
int t = read();
for(int i = 1; i <= t; ++i)sol();
return 0;
}
B. 二择(choice)
一组 个匹配需要 个点,那么随便找一个极大匹配,合法输出,不合法一定满足有至少 个没有边的点
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int read(){
int x = 0; bool f = 0; char c = getchar();
while(!isdigit(c)){f = c == '-'; c = getchar();}
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return f ? -x : x;
}
const int maxn = 1500005;
int n, m;
struct edge{int u, v;}e[maxn];
bool vis[maxn];
vector<int> ans;
void sol(){
n = read(), m = read();
for(int i = 1; i <= m; ++i){
int u = read(), v = read();
e[i] = {u, v};
}
ans.clear();
for(int i = 1; i <= n + n + n; ++i)vis[i] = false;
for(int i = 1; i <= m; ++i){
int u = e[i].u, v = e[i].v;
if(vis[u] || vis[v])continue;
vis[u] = vis[v] = 1;
ans.push_back(i);
}
if(ans.size() >= n){
printf("Beta2\n");
for(int i = 0; i < n; ++i)printf("%d ",ans[i]);printf("\n");
return;
}
ans.clear();
for(int i = 1; i <= n + n + n; ++i)if(!vis[i])ans.push_back(i);
printf("Beta1\n");
for(int i = 0; i < n; ++i)printf("%d ",ans[i]);printf("\n");
}
int main(){
freopen("choice.in","r",stdin);
freopen("choice.out","w",stdout);
int t = read();
for(int i = 1; i <= t; ++i)sol();
return 0;
}
C. 数塔(pyramid)
二分答案,转化为
然后观察性质,写成正三角(居中对齐)
如果存在连续的一段(至少两个) 那么他们上面一定都是他们,而且如果与之相邻的有 交错,那么他会每次扩展一个
所以当存在连续段时,找到最先扩展到正中间的即为答案
如果全是 交错,那么直接取两边即可
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 300005;
int n;
int a[maxn], b[maxn];
bool check(int mid){
for(int i = 1; i <= n + n - 1; ++i)b[i] = a[i] >= mid;
for(int i = n - 1, j = n + 1; i >= 1 && j <= n + n - 1; --i, ++j){
if(b[i] == b[i + 1])return b[i];
if(b[j] == b[j - 1])return b[j];
}
return b[1];
}
void sol(){
n = read();
for(int i = 1; i <= n + n - 1; ++i)a[i] = read();
int l = 1, r = n + n - 1, ans;
while(l <= r){
int mid = (l + r) >> 1;
if(check(mid))l = mid + 1, ans = mid;
else r = mid - 1;
}
printf("%d\n",ans);
}
int main(){
freopen("pyramid.in","r",stdin);
freopen("pyramid.out","w",stdout);
int t = read();
for(int i = 1; i <= t; ++i)sol();
return 0;
}
D. 环游(tour)
发现能走直接走,不能走才会跳跃,而且最多跳 次
于是对 种长度,把直接能到的位置看成一个点
考场想到这里就去考虑树形 了
考虑状压,每个深度我们只能选择一次,那么状态就压选过的深度
考虑每次我们会从一个子段出发,于是我们还需要走一个前缀和一个后缀,于是分 进行转移
令 表示使用了 深度, 能够拼出的最长前缀
类似,转移考虑新拼上一段未出现的深度
统计答案的时候,枚举前缀使用的状态 , 后缀使用其补集,看能否完全覆盖整个区间
因为我们最多跳 次,所以区间多于 无解,于是总的复杂度为
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int read(){
int x = 0; bool f = 0; char c = getchar();
while(!isdigit(c)){f = c == '-'; c = getchar();}
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return f ? -x : x;
}
const int maxn = 300005;
int n, v, x[maxn];
int l[19][maxn], r[19][maxn];
int pre[1 << 19], suf[1 << 19];
int main(){
freopen("tour.in","r",stdin);
freopen("tour.out","w",stdout);
n = read(), v = read();
for(int i = 1; i <= n; ++i)x[i] = read();
int mx = __lg(v) + 1;
for(int i = 0; i <= mx; ++i){
l[i][1] = 1; r[i][n] = n;
for(int j = 1 + 1; j <= n; ++j)if(x[j] - x[j - 1] <= (v >> i))l[i][j] = l[i][j - 1]; else l[i][j] = j;
for(int j = n - 1; j >= 1; --j)if(x[j + 1] - x[j] <= (v >> i))r[i][j] = r[i][j + 1]; else r[i][j] = j;
}
memset(suf, 0x3f, sizeof(suf));
suf[0] = n + 1;
for(int i = 0; i < (1 << mx); ++i){
for(int j = 1; j <= mx; ++j){
if((i >> (j - 1)) & 1)continue;
pre[i | (1 << (j - 1))] = max(pre[i | (1 << (j - 1))], r[j][min(pre[i] + 1, n)]);
suf[i | (1 << (j - 1))] = min(suf[i | (1 << (j - 1))], l[j][max(suf[i] - 1, 1)]);
}
}
int cnt = 0;
for(int i = 1; i <= n; i = r[0][i] + 1) ++cnt;
if(cnt > mx + 1){
for(int i = 1; i <= n; ++i)printf("Impossible\n");
}else{
for(int i = 1; i <= n; i = r[0][i] + 1){
bool fl = false;
for(int j = 0; j < (1 << mx) && !fl; ++j)if(pre[j] >= i - 1 && suf[((1 << mx) - 1) ^ j] <= r[0][i] + 1)fl = 1;
for(int j = i; j <= r[0][i]; ++j)if(fl)printf("Possible\n");else printf("Impossible\n");
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效