点此看题面

大致题意: 给你一个长度为\(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」蛐蛐国的修墙方案(搜索技巧题)的更多相关文章

  1. loj6043 「雅礼集训 2017 Day7」蛐蛐国的修墙方案

    传送门:https://loj.ac/problem/6043 [题解] 我们考虑这是个置换,所以一定形成了很多不相交的环. 对于每个环,我们只能选一段.不选.选一段.不选这样交替下去. 显然只有偶环 ...

  2. LOJ #6043. 「雅礼集训 2017 Day7」蛐蛐国的修墙方案

    我可以大喊一声这就是个SB题吗? 首先讲一句如果你像神仙CXR一样精通搜索你就可以得到\(80pts\)(无Subtask)的好成绩 我们考虑挖掘一下题目的性质,首先发现这是一个置换,那么我们发现这的 ...

  3. 【复杂度分析】loj#6043. 「雅礼集训 2017 Day7」蛐蛐国的修墙方案

    感觉有点假 题目大意 数据范围:$n<=100$ 题目分析 由于题目给出的是 置换,所以相当于只需枚举每个环的两个状态. 主要是复杂度分析这里: 一元环:不存在 二元环:特判保平安 三元环:不存 ...

  4. loj 6043「雅礼集训 2017 Day7」蛐蛐国的修墙方案

    loj 爆搜? 爆搜! 先分析一下,因为我们给出的是一个排列,然后让\(i\)给\(p_i\)连边,那么我们一定会得到若干个环,最后要使得所有点度数为1,也就是这些环有完备匹配,那么最后一定全是偶环. ...

  5. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

  6. 「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心)

    题面 来源 「 雅 礼 集 训 2017 D a y 7 」 跳 蚤 王 国 的 宰 相   传 统 2000   m s 1024   M i B {\tt「雅礼集训 2017 Day7」跳蚤王国的 ...

  7. 【LOJ 6041】「雅礼集训 2017 Day7」事情的相似度

    Description 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的 ...

  8. 【刷题】LOJ 6041 「雅礼集训 2017 Day7」事情的相似度

    题目描述 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的有相同的事情发 ...

  9. LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度

    我可以大喊一声这就是个套路题吗? 首先看到LCP问题,那么套路的想到SAM(SA的做法也有) LCP的长度是它们在parent树上的LCA(众所周知),所以我们考虑同时统计多个点之间的LCA对 树上问 ...

随机推荐

  1. 通过JS,按照原比例控制图片尺寸

    <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con ...

  2. java线程类图

    Executors创建不同类型的Executor, executor执行不同的runnable task Executor: Runnable:

  3. 「linux」后台启动nohup经常跟的>/dev/null 2>&1是什么意思

    https://www.cnblogs.com/wangsongbai/p/10215155.html 我们在写启动脚本的时候,会用nohup &,这个大家都知道,但是经常会有 >/de ...

  4. HAL库延时、SYCCNT与SYSTICK

    HAL库驱动中,由于某些外设的驱动需要使用超时判断(比如I2C.SPI.SDIO等),需要精确延时(精度为1ms),使用的是SysTick,但是在操作系统里面,我们需要使用SysTick来提供系统时基 ...

  5. VS Ctrl + Shift + Q

    在VS中按 Ctrl + Shift + Q 可以快速查找 void OnCollisionStay  等方法. void OnCollisionStay(Collision collision) { ...

  6. 批量删除QQ空间说说

    第一步:用电脑打开浏览器登录你的QQ空间 第二步:点击你的说说栏目 第三步:按下电脑的F12键或者点击右上角的菜单一栏,点击开发者工具 第四步:看到右半边屏幕,找到一个叫Console的菜单,并且点击 ...

  7. JetBrains IDE激活

    License server(服务器地址为http://idea.iteblog.com/key.php) Active Code:生成网址:http://idea.iteblog.com/

  8. 云计算&大数据相关知识

    1.极客学院云计算&大数据总链接:http://wiki.jikexueyuan.com/list/cloud/ 一.NSQ相关参考资料: 1.极客学院NSQ指南:http://wiki.ji ...

  9. maven课程 项目管理利器-maven 4-1 使用maven创建web项目 5星

    本节主要讲了使用maven创建web项目 主要分这三大类: 1 新建maven  web项目 2 后续处理普通java项目转web项目需要关注的点 3 maven特色转web需要关注的点 1 新建ma ...

  10. iOS中MD5加密字符串实现

    1.MD5加密 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321 ...