• 题解:[APIO2007]风铃


    你需要选一个满足下面两个条件的风铃:
    (1) 所有的玩具都在同一层(也就是说,每个玩具到天花板之间的杆的个数是一样的)或至多相差一层。
    (2) 对于两个相差一层的玩具,左边的玩具比右边的玩具要更靠下一点。
    风铃可以按照下面的规则重新排列:任选一根杆,将杆两头的线“交换”。也就是解开一根杆左右两头的线,然后将它们绑到杆的另一头。这个操作不会改变更下面的杆上线的排列顺序。

    其实看着这个题目我第一反应是平衡树,像splay,fhq之类的可以完成的区间翻转操作,但是这个题目不同的是,他改变两个之后其内部的顺序不变,所以我们可以感性的分析出来反转的顺序对答案没有太多的影响

    分析:
    由于最大最小相差深度小于等于1,所以可以先dfs一遍,特判一下,0输出0,大于1就是-1(考试时候忘了特判就挂了),对于等于1情况,我们来分析一下什么时候需要翻转:

    - 左小右大
    - 左有小有大,右大
    - 左小,右有小有大

    所以,对于这个需要再来一次dfs,用0表示小,1表示大,2表示有小有大,遇到上面三种情况就ans++
    完整代码如下:

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    #define re register
    #define gc getchar()
    #define ll long long
    #define il inline
    const int N= 100010;
    il int read() {
        re int x(0),f(1);
        re char ch=gc;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=gc;
        }
        while(ch>='0'&&ch<='9') {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=gc;
        }
        return x*f;
    }
    int ls[N],rs[N],_max=-1,_min=1e8,deep[N],n,ans,flag=1;
    
    void dfs1(int u) {
        if(ls[u]) {
            deep[ls[u]]=deep[u]+1;
            dfs1(ls[u]);
        } else {
            _min=min(_min,deep[u]+1);
            _max=max(_max,deep[u]+1);
        }
        if(rs[u]) {
            deep[rs[u]]=deep[u]+1;
            dfs1(rs[u]);
        } else {
            _min=min(_min,deep[u]+1);
            _max=max(_max,deep[u]+1);
        }
    }
    
    namespace SP1 {
        int x[3][3]= {
            0,2,2,
            2,1,2,
            2,2,2,
        };
        int dfs(int u,int dep) {
            if(u==-1) {
                if(dep==_max-1) return 1;
                return 0;
            }
            int a=dfs(ls[u],dep+1);
            int b=dfs(rs[u],dep+1);
            if(a==0&&b==1) ++ans;
            if(a==2&&b==1) ++ans;
            if(a==0&&b==2) ++ans;
            if(a==2&&b==2) flag=0;
            return x[a][b];
        }
        int main() {
            dfs(1,0);
            if(!flag) {
                cout<<-1<<endl;
                return 0;
            }
            cout<<ans<<endl;
        }
    };
    int main() {
        
        n=read();
        for(int i=1; i<=n; ++i)
            ls[i]=read(),rs[i]=read();
        dfs1(1);
        if(_max-_min==1) {
            SP1::main();
            return 0;
        }
        if(_max==_min) cout<<0;
        cout<<-1;
    
        return 0;
    }

    很多大佬莫名MLE了,但是这个的空间是足够的,只用了16M

  • 相关阅读:
    【Framework】HTTP运行期与页面执行模型
    【Framework】深入研究Asp.net页面的生命周期
    【WCF】Silverlight+wcf+自定义用户名密码验证
    【缓存】EF4ProviderWrappers
    【缓存】Sql Server 2005/2008 SqlCacheDependency查询通知的使用总结
    【缓存】利用Cache防止同一帐号重复登录
    【缓存】.net中Cache管理操作
    【缓存】系统缓存全解析 (上)
    【缓存】系统缓存全解析 (中)
    【缓存】系统缓存全解析 (下)
  • 原文地址:https://www.cnblogs.com/zijinjun/p/10596489.html
Copyright © 2020-2023  润新知