专栏文章
题解:P14406 [JOISC 2015] 愉快的标志设计 / En-JOI-able Logo Design
P14406题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min4kb2k
- 此快照首次捕获于
- 2025/12/01 20:28 3 个月前
- 此快照最后确认于
- 2025/12/01 20:28 3 个月前
比较小清新的题目。
发现题目给出的序列很明显就是由 个更小的序列组合而来的,所以我们自然而然的想到递归搜索。
不难发现,对于前 个小序列,代价都是一样的算法,只要看有多少个合法的,再用区间长度减去就行了。
但是对于最后一种序列,我们发现和当前处理的序列是属于同一种类型,但是问题规模更小。所以对于最后一种序列我们递归求解就好了。
分析时间:求解前 种序列可以用前缀和预处理,这里是 的。对于递归求解部分,明显和递归深度有关,每次递归深度减一,规模变为原先的 ,总共就是 的时间。所以单次求解的时间复杂度就是 。
因为可以从任意起点出发,我们破环成链,预处理前缀和,再枚举起点,总共枚举 次,单次 ,总复杂度就是 的,可以通过。
代码
CPP#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define V vector
#define FOR(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define pb push_back
const int INF=1e9+10;
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int k;cin>>k;
string s;cin>>s;
int n=(1<<(2*k));
V<int>num(2*n+1),sumj(2*n+1,0),sumo(2*n+1,0),sumi(2*n+1,0);
FOR(i,1,n) num[i]=num[i+n]=s[i-1];
FOR(i,1,2*n){
sumj[i]=sumj[i-1]+(num[i]=='J');
sumo[i]=sumo[i-1]+(num[i]=='O');
sumi[i]=sumi[i-1]+(num[i]=='I');
}
function<int(int,int)>dfs=[&](int dep,int l){
if(dep==0) return 0;
int l1=l+(1<<(2*(dep-1))),l2=l1+(1<<(2*(dep-1))),l3=l2+(1<<(2*(dep-1)));
int ans1=sumj[l1-1]-sumj[l-1];
int ans2=sumo[l2-1]-sumo[l1-1];
int ans3=sumi[l3-1]-sumi[l2-1];
return l3-l-(ans1+ans2+ans3)+dfs(dep-1,l3);
};
int ans=INF;
FOR(i,1,n){
ans=min(ans,dfs(k,i));
}
cout<<ans;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...