【LOJ6043】「雅礼集训 2017 Day7」蛐蛐国的修墙方案(搜索技巧题)
大致题意: 给你一个长度为\(n\)的排列\(p\),要求构造一个合法的括号序列,使得如果第\(i\)个位置是左括号,则第\(p_i\)个位置一定是右括号。
暴搜
很容易想出一个暴搜。
即对于每一个没有确定的位置\(x\),无非有两种情况:
- 选左括号。前提是\(p_x\)没被选过或者\(p_x\)为右括号,然后标记第\(p_x\)位为右括号。
- 选右括号。我们可以开一个变量\(v\)来记录左括号个数\(-\)有括号个数,则选右括号的前提是\(v>0\)。(因为要是一个合法的括号序列)
最后判断\(v\)是否恰好等于\(0\)即可。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100
using namespace std;
int n,a[N+5];char s[N+5];
I void dfs(CI x,CI v)//x记录当前位置,v记录左括号个数减右括号个数
{
if(x>n) return (void)(!v&&(puts(s+1),exit(0),0));//如果x大于n且v恰好为0,则输出答案,退出程序
if(s[x])//如果已经确定
{
if(s[x]^')') return dfs(x+1,v+1);//如果是左括号,搜索下一位
if(v) return dfs(x+1,v-1);return;//如果是右括号且v大于0,搜索下一位
}
if(a[x]>x||s[a[x]]^'(') s[x]='(',s[a[x]]=')',dfs(x+1,v+1),s[x]=s[a[x]]='\0';//选左括号
if(v) s[x]=')',dfs(x+1,v-1),s[x]='\0';//选右括号
}
int main()
{
RI i;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i);//读入
return dfs(1,0),0;
}
所以这样就有\(81\)分了。
如果你是常数之神,说不定能直接过。
观察性质
接下来,我们要观察一下这个题目中的一个性质。
注意到它保证有解,再结合题意,如果我们把\(i->p_i\)看成一条边,则原序列可以看成若干个环,而这些环一定都是偶环(不然就无解了)。
而对于一个偶环,我们对它的选择必然是左括号与右括号相交替的。
也就是说,对于一个偶环,只有两种选择方法,似乎暴枚即可。
然而,要特判环长为\(2\)的情况(不然会像我第一次那样只有\(86\)分——也就比暴搜多\(5\)分),贪心一下即可发现肯定是左边那位选左括号,右边那位选右括号。
这样就能过了。
关于时间复杂度有严谨的证明:
考虑我们特判了环长为\(2\)的情况,也就是说环长至少为\(4\)。
则最多\(100÷4=25\)个环,而\(2^{25}\)稳过。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100
using namespace std;
int n,tot,a[N+5],v[N+5];char s[N+5];vector<int> f[N+5];
I void Check()//验证是否为合法括号序列
{
for(RI i=1,t=0;i<=n;++i) if((t+=(s[i]^')'?1:-1))<0) return;//若出现不合法,直接退出函数
puts(s+1),exit(0);//合法则输出答案,退出程序
}
I void dfs(CI x)//搜索,判断第i个环的填法
{
if(x>tot) return Check();RI i,sz=f[x].size();
if(!(sz^2)) return s[f[x][0]]='(',s[f[x][1]]=')',dfs(x+1);//特判环长为2的情况
for(i=0;i^sz;++i) s[f[x][i]]=(i&1?'(':')');dfs(x+1);//环中必然是左右括号交替
for(i=0;i^sz;++i) s[f[x][i]]=(i&1?')':'(');dfs(x+1);//枚举另一种情况
}
int main()
{
RI i,x;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i);//读入
for(i=1;i<=n;++i) if(!v[x=i])//如果没访问过
{++tot;W(!v[x]) v[x]=1,f[tot].push_back(x),x=a[x];}//找环
return dfs(1),0;//搜索
}
【LOJ6043】「雅礼集训 2017 Day7」蛐蛐国的修墙方案(搜索技巧题)的更多相关文章
- loj6043 「雅礼集训 2017 Day7」蛐蛐国的修墙方案
传送门:https://loj.ac/problem/6043 [题解] 我们考虑这是个置换,所以一定形成了很多不相交的环. 对于每个环,我们只能选一段.不选.选一段.不选这样交替下去. 显然只有偶环 ...
- LOJ #6043. 「雅礼集训 2017 Day7」蛐蛐国的修墙方案
我可以大喊一声这就是个SB题吗? 首先讲一句如果你像神仙CXR一样精通搜索你就可以得到\(80pts\)(无Subtask)的好成绩 我们考虑挖掘一下题目的性质,首先发现这是一个置换,那么我们发现这的 ...
- 【复杂度分析】loj#6043. 「雅礼集训 2017 Day7」蛐蛐国的修墙方案
感觉有点假 题目大意 数据范围:$n<=100$ 题目分析 由于题目给出的是 置换,所以相当于只需枚举每个环的两个状态. 主要是复杂度分析这里: 一元环:不存在 二元环:特判保平安 三元环:不存 ...
- loj 6043「雅礼集训 2017 Day7」蛐蛐国的修墙方案
loj 爆搜? 爆搜! 先分析一下,因为我们给出的是一个排列,然后让\(i\)给\(p_i\)连边,那么我们一定会得到若干个环,最后要使得所有点度数为1,也就是这些环有完备匹配,那么最后一定全是偶环. ...
- 「雅礼集训 2017 Day7」事情的相似度
「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...
- 「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心)
题面 来源 「 雅 礼 集 训 2017 D a y 7 」 跳 蚤 王 国 的 宰 相 传 统 2000 m s 1024 M i B {\tt「雅礼集训 2017 Day7」跳蚤王国的 ...
- 【LOJ 6041】「雅礼集训 2017 Day7」事情的相似度
Description 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的 ...
- 【刷题】LOJ 6041 「雅礼集训 2017 Day7」事情的相似度
题目描述 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的有相同的事情发 ...
- LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度
我可以大喊一声这就是个套路题吗? 首先看到LCP问题,那么套路的想到SAM(SA的做法也有) LCP的长度是它们在parent树上的LCA(众所周知),所以我们考虑同时统计多个点之间的LCA对 树上问 ...
随机推荐
- iOS自动化测试的那些干货
前言 如果有测试大佬发现内容不对,欢迎指正,我会及时修改. 大多数的iOS App(没有持续集成)迭代流程是这样的 也就是说,测试是发布之前的最后一道关卡.如果bug不能在测试中发现,那么bug就会抵 ...
- python 列表学习
一.创建一个列表(list)_使用逗号分隔不同的数据项,使用方括号括起来. list = [1,2,3,4,5,6,7] 与字符串的索引一样,列表索引从 0 开始,列表可以截取.组合. 二.访问列表中 ...
- Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) F. Substrings in a String
http://codeforces.com/contest/914/problem/F 以前做过一个类似的,但是查询的子串长度最多是10,这个时候就是用bit + hash做了.这是因为改变一个字符, ...
- WSGI学习系列多种方式创建WebServer
def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) ...
- Python 元组 (tuple)
作者博文地址:https://www.cnblogs.com/liu-shuai/ Python的元组与列表类似,同样可通过索引访问,支持异构,任意嵌套.不同之处在于元组的元素不能修改.元组使用小括号 ...
- Cloudera Manager卸载笔记
1.通过管理平台分别停止组件服务和Cloudera Management Service 2.通过管理平台注销并移除Parcles (在控制台注销并移除,无论是安装的Parcles还是未安装的Parc ...
- Andrew Ng 的 Machine Learning 课程学习 (week3) Logistic Regression
这学期一直在跟进 Coursera上的 Machina Learning 公开课, 老师Andrew Ng是coursera的创始人之一,Machine Learning方面的大牛.这门课程对想要了解 ...
- HUD 5593——ZYB's Tree——————【树形dp】
ZYB's Tree Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Tota ...
- HDU 5446——Unknown Treasure——————【CRT+lucas+exgcd+快速乘+递推求逆元】
Each test case starts with three integers n,m,k(1≤m≤n≤1018,1≤k≤10) on a line where k is the number o ...
- javaSE练习2——流程控制_2.2
一.假设某员工今年的年薪是30000元,年薪的年增长率6%.编写一个Java应用程序计算该员工10年后的年薪,并统计未来10年(从今年算起)总收入. package com.test; public ...