AtCoder Grand Contest 012 C
感觉APIO2022的最后一题就是从这题改来的,简化了一些后又加上了一些奇怪的优化。
首先我们将这题转成和APIO2022一样的格式——如果我们将最终答案分为两个部分,前半部分有个上升子序列,并且值域在到,后半部分是的序列。不难发现这个构造出的序列一定有个符合题目要求的子序列。
比如时,有:
1 2 3 1 2 3
那么前半部分有这个上升子序列,后半部分也有唯一对应的相等串,比如。
再比如时,有
3 2 4 1 5 1 2 3 4 5
前半部分有这个上升子序列,后半部分也有对应的相等串,比如。
至此,我们就将题面转化为:
构造一个长度不超过(因为后面我们还要重复一遍)的数列,使得上升子序列个数为。
这里我们暂且认为空子序列也是上升的,也就是我们要求出有个上升子序列的数列。
那么不难发现,如果我们当前有一个数列,如果我们加入,则上升子序列个数;加入,则上升子序列个数。
故我们可以将二进制分解,从而得到每一处位置是加入一个最小值还是最大值,从而求出整个数列。
这样,我们使用的数不超过,数列的长度不超过,可以AC。
#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl
using ll=long long;
ll n,id,num,a[205];
std::vector<ll> tp,smallest,biggest;
int main() {
scanf("%lld",&n); n++;
ll dig=0,temp=1; while(temp<=n) dig++,temp<<=1ll; dig--;
for(int i=1;i<=dig;i++) tp.push_back(0);
ll p=(ll)tp.size(),d=0;
while(p>0) {
if(n&(1ll<<d)) tp.insert(tp.begin()+p,1);
p--; d++;
}
for(auto item : tp) {
if(item) smallest.push_back(++id);
else biggest.push_back(++id);
}
for(int i=(int)smallest.size()-1;~i;i--) a[smallest[i]]=++num;
for(int i=0;i<(int)biggest.size();i++) a[biggest[i]]=++num;
for(int i=1;i<=num;i++) a[++id]=i;
printf("%d\n",id); for(int i=1;i<=id;i++) printf("%d ",a[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异