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

我可以大喊一声这就是个SB题吗?

首先讲一句如果你像神仙CXR一样精通搜索你就可以得到\(80pts\)(无Subtask)的好成绩

我们考虑挖掘一下题目的性质,首先发现这是一个置换,那么我们发现这的显然会成环

然后我们发现那个度数的性质其实就是告诉你环上的点必须左右括号相间

换而言之一个环其实只有两种状态,那么我们对于每一个环进行搜索的复杂度显然就是\(O(2^{\frac{n}{2}}n)\)

那么考虑\(n=100\)要怎么卡过去。我们发现一个长度为\(2\)的环显然必须令前面的为左括号,后面为右括号

然后细细分析一下复杂度,这样只用长度\(\ge4\)的环需要搜索状态,那么复杂度就是\(2^{\frac{n}{4}} n\),足以通过此题

CODE

#include<cstdio>
#include<vector>
#include<cstdlib>
#define RI register int
#define CI const int&
using namespace std;
const int N=105;
int n,x,cur,p[N],col[N],sz[N]; vector <int> v[N]; bool c[N];
inline void check(int pfx=0)
{
    RI i; for (i=1;i<=n;++i)
    {
        pfx+=c[i]?-1:1; if (pfx<0) return;
    }
    for (i=1;i<=n;++i) putchar(c[i]?')':'('); exit(0);
}
inline void DFS(CI nw)
{
    if (nw>cur) return check(); if (sz[nw]==2)
    return (void)(c[v[nw][0]]=0,c[v[nw][1]]=1,DFS(nw+1));
    RI i; for (i=0;i<sz[nw];++i) c[v[nw][i]]=i&1; DFS(nw+1);
    for (i=0;i<sz[nw];++i) c[v[nw][i]]=(i&1)^1; DFS(nw+1);
}
int main()
{
    //freopen("C.in","r",stdin); freopen("C.out","w",stdout);
    RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&p[i]);
    for (i=1;i<=n;++i) if (!col[i])
    {
        for (x=i,++cur;!col[x];x=p[x])
        col[x]=cur,v[cur].push_back(x),++sz[cur];
    }
    return DFS(1),0;
}
posted @ 2019-04-08 20:55 hl666 阅读(...) 评论(...) 编辑 收藏