• HDU 6044


    研究一下建树 :

    /*
    HDU 6044 - Limited Permutation [ 读入优化,笛卡尔树 ]  |  2017 Multi-University Training Contest 1
    题意:
    	给出两组序列 l[i], r[i], 代表以 p[i] 为最小值所在的区间的边界
    	问 满足这些条件的序列 p 的个数
    分析:
    	必定能找到一个p[i] 使得 l[i] == 1, r[i] == n ,其将数组分成两块[1, i-1], [i+1, n]
    	以之为根节点,将区间为[1, i-1] 和 [i+1, n] 的节点作为左右儿子,再在每一块上递归地进行划分,则构成一棵笛卡尔树
    	能构成的笛卡尔树的形状是唯一的,若不能构成,则 ans = 0
    	若能构成,则 以i为根的子树的方案数 f(i) = C(size_l+size_r, size_l) * f(l) * f(r)
    
    	数据很多用fread读入
    */
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int N = 1e6+5;
    const LL MOD = 1e9+7;
    namespace IO {
        const int MX = 4e7; //1e7 占用内存 11000kb
        char buf[MX]; int c, sz;
        void begin() {
            c = 0;
            sz = fread(buf, 1, MX, stdin);//一次性全部读入
        }
        inline bool read(int &t) {
            while (c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
            if (c >= sz) return false;//若读完整个缓冲块则退出
            bool flag = 0; if(buf[c] == '-') flag = 1, c++;
            for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
            if(flag) t = -t;
            return true;
        }
    }
    namespace COMB {
    	int F[N], Finv[N], inv[N];//F是阶乘,Finv是逆元的阶乘
    	void init(){
    		inv[1] = 1;
    		for(int i = 2; i < N; i ++){
    			inv[i] = (MOD - MOD / i) * 1LL * inv[MOD % i] % MOD;
    		}
    		F[0] = Finv[0] = 1;
    		for(int i = 1; i < N; i ++){
    			F[i] = F[i-1] * 1LL * i % MOD;
    			Finv[i] = Finv[i-1] * 1LL * inv[i] % MOD;
    		}
    	}
    	int comb(int n, int m){//comb(n, m)就是C(n, m)
    		if(m < 0 || m > n) return 0;
    		return F[n] * 1LL * Finv[n - m] % MOD * Finv[m] % MOD;
    	}
    }
    struct Node
    {
        int f, l, r;
    }T[N];
    int l[N], r[N];
    int n;
    int q[N], top;
    inline bool cmp(const int& a,const int& b) {
        return (r[a] - l[a]) < (r[b] - l[b]);
    }
    int Build()
    {
        top = 0;
        for (int i = 1; i <= n; i++)
        {
            int k = top;
            while (k && cmp(q[k-1], i)) --k;
            if (k != 0)
            {
                T[i].f = q[k-1];
                T[q[k-1]].r = i;
            }
            if (k != top)
            {
                T[q[k]].f = i;
                T[i].l = q[k];
            }
            q[k++] = i;
            top = k;
        }
        return q[0];
    }
    bool flag;
    LL ans;
    LL dfs(int x, int L, int R)
    {
        if (!x) return 1;
        if (!flag) return 0;
        if (l[x] != L || r[x] != R) return 0;
        LL res = COMB::comb(R-L, R-x);
        res = res * dfs(T[x].l, L, x-1) % MOD;
        res = res * dfs(T[x].r, x+1, R) % MOD;
        if (res == 0) flag = 0;
        return res;
    }
    int main()
    {
        COMB::init();
        IO::begin();
        for (int tt = 1; IO::read(n); ++tt)
        {
            for (int i = 1; i <= n; i++) T[i].l = T[i].r = T[i].f = 0;
            for (int i = 1; i <= n; i++) IO::read(l[i]);
            for (int i = 1; i <= n; i++) IO::read(r[i]);
            int root = Build();
            flag = 1;
            ans = dfs(root, 1, n);
            printf("Case #%d: %lld
    ", tt, ans);
        }
    }
    

      要么直接 map

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int N = 1e6+5;
    const LL MOD = 1e9+7;
    namespace fastIO {
    	#define BUF_SIZE 100000
    	//fread -> read
    	bool IOerror = 0;
    	inline char nc() {
    		static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
    		if(p1 == pend) {
    			p1 = buf;
    			pend = buf + fread(buf, 1, BUF_SIZE, stdin);
    			if(pend == p1) {
    				IOerror = 1;
    				return -1;
    			}
    		}
    		return *p1++;
    	}
    	inline bool blank(char ch) {
    		return ch == ' ' || ch == '
    ' || ch == '
    ' || ch == '	';
    	}
    	inline void read(int &x) {
    		char ch;
    		while(blank(ch = nc()));
    		if(IOerror)
    			return;
    		for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    	}
    	#undef BUF_SIZE
    }
    namespace COMB {
    	int F[N], Finv[N], inv[N];//F是阶乘,Finv是逆元的阶乘
    	void init(){
    		inv[1] = 1;
    		for(int i = 2; i < N; i ++){
    			inv[i] = (MOD - MOD / i) * 1LL * inv[MOD % i] % MOD;
    		}
    		F[0] = Finv[0] = 1;
    		for(int i = 1; i < N; i ++){
    			F[i] = F[i-1] * 1LL * i % MOD;
    			Finv[i] = Finv[i-1] * 1LL * inv[i] % MOD;
    		}
    	}
    	int comb(int n, int m){//comb(n, m)就是C(n, m)
    		if(m < 0 || m > n) return 0;
    		return F[n] * 1LL * Finv[n - m] % MOD * Finv[m] % MOD;
    	}
    }
    typedef pair<int, int> P;
    using namespace fastIO;
    map<P, int> mp;
    int t, n;
    int l[N], r[N];
    LL dfs(int l, int r)
    {
        if (l > r) return 1;
        int x = mp[P(l, r)];
        if (!x) return 0;
        LL ans = COMB::comb(r-l, r-x);
        ans = ans * dfs(l, x-1) % MOD;
        ans = ans * dfs(x+1, r) % MOD;
        return ans;
    }
    int main()
    {
        COMB::init();
        for (int tt = 1; read(n), !IOerror; ++tt)
        {
            mp.clear();
            for (int i = 1; i <= n; i++) read(l[i]);
            for (int i = 1; i <= n; i++) read(r[i]);
            for (int i = 1; i <= n; i++)
                mp[P(l[i], r[i])] = i;
            LL ans = dfs(1, n);
            printf("Case #%d: %lld
    ", tt, ans);
        }
    }
    

      

    我自倾杯,君且随意
  • 相关阅读:
    GC 打印日志配置
    Java查看Old代对象具体信息
    Java 进程 OOM 的排查分析(glibc 篇)
    排障 v2 堆外内存泄漏
    HotSpot VM的Native Memory Tracking
    gc日志深入解析
    排障 v1
    图和图算法js
    export与export default的区别
    leftNav
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/7247470.html
Copyright © 2020-2023  润新知