• 【51nod】1934 受限制的排列


    题解

    这题还要判无解真是难受……

    我们发现我们肯定能确定1的位置,1左右的两个区间是同理的可以确定出最小值的位置

    我们把区间最小值看成给一个区间+1,构建出笛卡尔树,就求出了每一次取最小值和最小值左右的区间大小
    然后就相当于左右子树的排列方式,乘上把左右子树那么多个元素选出左子树个数和右子树个数那么多的方案数,是个普通的组合数

    判无解从根开始,要求根的区间是[1,N],左右区间是[1,rt-1][rt + 1,R]递归判下去就好

    复杂度(O(n))
    但是跑得奇慢无比= =,我脑子一抽把数组改成两倍居然过了。。。卡着时限过的。。。不想写fread(懒.jpg)

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define MAXN 2000005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    template<class T>
    void read(T &res) {
    	res = 0;char c = getchar();T f = 1;
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		res = res * 10 + c - '0';
    		c = getchar();
    	}
    	res *= f;
    }
    template<class T>
    void out(T x) {
    	if(x < 0) {putchar('-');x = -x;}
    	if(x >= 10) {
    		out(x / 10);
    	}
    	putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    
    int N;
    int L[MAXN],R[MAXN],S[MAXN],fac[MAXN],inv[MAXN],invfac[MAXN],lc[MAXN],rc[MAXN],rt;
    int sta[MAXN],top;
    int inc(int a,int b) {
    	return a + b >= MOD ? a + b - MOD : a + b;
    }
    int mul(int a,int b) {
    	return 1LL * a * b % MOD;
    }
    int C(int n,int m) {
    	if(n < m) return 0;
    	return mul(mul(fac[n],invfac[m]),invfac[n - m]);
    }
    bool check(int u,int fa,int l,int r) {
    	if(!u && l <= r) return false;
    	else if(!u) return true; 
    	if(L[u] != l || R[u] != r) return false;
    	if(S[u] == fa + 1) {
    		return check(lc[u],S[u],l,u - 1) && check(rc[u],S[u],u + 1,r);
    	}
    	else return false;
    }
    int dfs(int u,int L,int R) {
    	if(!u) return 1;
    	return mul(mul(dfs(lc[u],L,u - 1),dfs(rc[u],u + 1,R)),C(R - L,u - L));
    }
    void Init() {
    	for(int i = 1 ; i <= N ; ++i) {lc[i] = rc[i] = 0;S[i] = 0;read(L[i]);}
    	for(int i = 1 ; i <= N ; ++i) {read(R[i]);S[L[i]]++;S[R[i] + 1]--;}
    	top = 0;int k;
    	for(int i = 1 ; i <= N ; ++i) {
    		S[i] += S[i - 1];
    		if(S[i] == 1) {rt = i;}
    		k = top;
    		while(k >= 1 && S[sta[k]] > S[i]) --k;
    		if(k + 1 <= top) lc[i] = sta[k + 1];
    		if(k) rc[sta[k]] = i;
    		top = k;
    		sta[++top] = i;
    	}
    }
    void Solve() {
    	if(!check(rt,0,1,N)) {out(0);enter;return;}
    	out(dfs(rt,1,N));enter;
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	int cnt = 0;
    	fac[0] = 1;
    	for(int i = 1 ; i <= 1000000 ; ++i) fac[i] = mul(fac[i - 1],i);
    	inv[0] = inv[1] = 1;
    	for(int i = 2 ; i <= 1000000 ; ++i) inv[i] = mul(inv[MOD % i],MOD - MOD / i);
    	invfac[0] = 1;
    	for(int i = 1 ; i <= 1000000 ; ++i)	invfac[i] = mul(invfac[i - 1],inv[i]);
    	while(scanf("%d",&N) != EOF) {
    		++cnt;
    		printf("Case #%d: ",cnt);
    		Init();
    		Solve();
    	}
    }
    

    不能再颓了!还有34天就NOI了!

    时间太慢了,但是我又怕它太快了

  • 相关阅读:
    nginx重启命令
    Java中Vector笔记
    JAVA中字符串比较equals()和equalsIgnoreCase()的区别
    HashMap和TreeMap的常用排序方法
    Logger用法
    HashMap和Hashtable的区别
    class.getDeclaredFields()与class.getFields()
    java中 文件压缩处理
    Java远程执行Shell命令
    python 学习笔记 redis操作
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9175161.html
Copyright © 2020-2023  润新知