• [AGC058C]Planar Tree


    Planar Tree

    题解

    首先,我们看这题呀,感觉这东西好像很阴间的样子,想想有没有什么比较好的方法。
    好像没有的样子。
    首先当然可以有比较简单的 O ( n 3 ) O\left(n^3\right) O(n3)的区间 d p dp dp做法,不过这东西好像根本没有利用上我们 A i ∈ [ 1 , 4 ] A_i\in[1,4] Ai[1,4]的性质。
    不妨考虑一下这个性质有什么用。

    显然,这里我们可以发现, A i = 1 / 4 A_i=1/4 Ai=1/4的点连接到的点的权值都是唯一的,它们如果与 2 / 3 2/3 2/3相邻,显然可以直接合并到那上面。
    同样,如果有两个相邻的权值相同的数,也是可以合并到一起的,因为它们必然可以连向相同的目标。
    我们可以把上面两类点给合并起来,得到一个相邻的点都不同并且不存在 ( 1 , 2 ) / ( 3 , 4 ) (1,2)/(3,4) (1,2)/(3,4)相邻的图形。

    但这又有什么用呢?
    我们可以发现,我们的树其实是可以由不断合并在环上相邻的边构成的。
    显然,对于一个大小为 n n n的环,其生成树上肯定会存在一个叶子与其父亲相邻,否则必然会出现相交的线段。
    也就是说,我们可以由这种方式递归构造出整棵树。
    我们上面的合并显然是优秀的合并,也就是说,它并不会影响最后的答案是否有解。
    那么我们再来看在我们的新环上有能怎么办了?
    如果这个环仅存在 2 2 2 3 3 3的时候显然是有解的,所以我们的目的是将这个环上的 1 , 4 1,4 1,4全部去掉。
    如果要去掉 1 1 1,环上肯定得存在 2 2 2,为了两者不相邻,它们肯定会用 3 3 3隔开,也是说能合并的地方必然长这个样子: . . . , 1 , 3 , 1 , 3 , 1 , 3 , 1 , 3 , 2 , . . . ...,1,3,1,3,1,3,1,3,2,... ...,1,3,1,3,1,3,1,3,2,...,这样我合并 ( 1 , 2 ) (1,2) (1,2)后必然会去掉一个 3 3 3
    同样,在合并 ( 3 , 4 ) (3,4) (3,4)后也必然去掉一个 2 2 2
    也就是说,我们有解的必要条件是 c n t 2 ⩾ c n t 4 ∧ c n t 3 ⩾ c n t 1 cnt_2\geqslant cnt_4\wedge cnt_3\geqslant cnt_1 cnt2cnt4cnt3cnt1
    但显然,它们两个不能同时取等,因为我们最后一次合并后肯定还会剩一个。
    所以,我们真正的必要条件是: ( c n t 2 ⩾ c n t 4 ∧ c n t 3 > c n t 1 ) ∨ ( c n t 2 > c n t 4 ∧ c n t 3 ⩾ c n t 1 ) (cnt_2\geqslant cnt_4\wedge cnt_3>cnt_1)\vee(cnt_2>cnt_4\wedge cnt_3\geqslant cnt_1) (cnt2cnt4cnt3>cnt1)(cnt2>cnt4cnt3cnt1)
    容易发现这个条件也是充分的,因为按照我们上面的方法是可以构造得到解的。

    所以,只需要按我们上面的方法缩点后判断一下即可。
    时间复杂度 O ( ∑ n ) O\left(\sum n\right) O(n)

    源码

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #include
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    #define MAXN 300005
    #define pb push_back
    #define mkpr make_pair
    #define fir first
    #define sec second
    #define lson (rt<<1)
    #define rson (rt<<1|1)
    const int INF=0x3f3f3f3f;
    const int mo=998244353;
    template<typename _T>
    void read(_T &x){
        _T f=1;x=0;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
        x*=f;
    }
    template<typename _T>
    _T Fabs(_T x){return x<0?-x:x;}
    int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
    void Add(int &x,int y,int p){x=add(x,y,p);}
    int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1;}return t;}
    int T,n,a[MAXN],b[MAXN],head,tail,cnt[5];
    int main(){
        read(T);
        while(T--){
            read(n);head=tail=0;
            for(int i=1;i<=n;i++){
                read(a[i]);a[i]--;bool flag=0;
                while(head<tail){
                    if(b[tail-1]==a[i]){tail--;continue;}
                    if((b[tail-1]^a[i])==1){
                        if(a[i]==0||a[i]==3)flag=1;
                        else{tail--;continue;}
                    }
                    break;
                }
                if(!flag)b[tail++]=a[i];
            }
            while(head+1<tail){
                if(b[head]==b[tail-1])tail--;
                else if((b[head]^b[tail-1])==1){
                    if(b[head]==0||b[head]==3)head++;
                    else tail--;
                }
                else break;
            }
            for(int i=head;i<tail;i++)cnt[b[i]]++;
            if(cnt[0]>cnt[2]||cnt[3]>cnt[1])puts("No");
            else if(cnt[0]==cnt[2]&&cnt[3]==cnt[1])puts("No");
            else puts("Yes");
            cnt[0]=cnt[1]=cnt[2]=cnt[3]=0;
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    谢谢!!!

  • 相关阅读:
    【蓝桥杯选拔赛真题03】C++输出字母Y 青少年组蓝桥杯C++选拔赛真题 STEMA比赛真题解析
    【计算机图形学】基础 - Colorization using Optimization
    java-php-net-python-基于ssh的酒店客房在线预定计算机毕业设计程序
    Gateway微服务路由使微服务静态资源加载失败
    从学校到工作的一些收获
    知名药企集中签约阿里健康,数字化健康服务成进博会热议话题
    京东小程序平台助力快送实现跨端
    LeetCode【78. 子集】
    来看看Python编码规范(PEP 8)
    短信在企业中的应用有哪些?
  • 原文地址:https://blog.csdn.net/Tan_tan_tann/article/details/126351251