hdu 5919 dfs前序遍历计数 笛卡尔树

题意:有n个区间,对于第i个区间[li,ri]有li<=i<=ri,
对于任意1<=L<=i<=R<=n,当前仅当li<=L<=i<=R<=ri时P[i]=min(P[L],P[L+1],…,P[R])

关键应该就是题目的 if and only if 当且仅当,就是指l r必须是pi管理的范围,再大都不是它管理的范围了,那么就是一个区间分治处理和合并了,这能想到和dfs序是一致的,所以用dfs,考虑 对于每个pi 它的左区间 li和 ri 无论你怎么分配其实都是可以得到 一个最小的数 第二小的数,那么就是怎么分配这些数,按理说 如果分配是可行的,那么每个以 P[i] 的i为分界线的区间,两边分治处理的小区间是不会产生冲突的 冲突是指,所有的区间递归的包含一个个更小的区间,而且被包含的区间不能跨过包含区间的pi 其实处理好,每个区间都是一直包含着别的区间,而且必然成立,所以建造笛卡尔树。先根据l最左,r最右排序,递归的找有没有冲突的区间,如果没有区间冲突, 那么区间的数其实你是可以随便放的,所以就是 C(区间总数-1(最小值已固定位置),左边区间的数)*dfs左得到左边内部的方案数(也就是位置的不同)*dfs右(同理)

所有的区间,要么是相互包含的,要么没有交集,不会出现有相交的情况。这个如何解释呢?我们们用反证法,假设区间[li,ri]与[lj,rj]相交,对于li

#include <bits/stdc++.h>
using namespace std;
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;  
    }  
}  

const int N = 1e6+100;
const int mod =1e9+7;
struct node
{
    int id,l,r;
}s[N+100];
typedef long long ll;


ll fac[N+100],inv[N+100];

int cmp(node a,node b)
{
    if(a.l==b.l) return a.r>b.r;
    return a.l<b.l;
}

ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res*=a,res%=mod;
        a*=a;
        a%=mod;
        b>>=1;
    }
    return res;
}

void init()
{
    fac[0]=1;
    for(int i=1;i<=N;i++)
        fac[i]=(fac[i-1]*i)%mod;
    inv[N]=qpow(fac[N],mod-2);
    for(int i=N-1;i>=0;i--)
    {
        inv[i]=inv[i+1]*(i+1);
        inv[i]%=mod;
    }
}
int mark,arr;


ll C(ll a,ll b)
{
    if(a<b) return 0;
    if(a==b) return 1;
    if(b==0) return 1;
    a%=mod,b%=mod;
    return ((fac[a]*inv[b])%mod*inv[a-b])%mod;

}

ll dfs(int l,int r)
{
    if(mark==0)
        return 0;
    if(l>r) return 1;
    if(l!=s[arr].l||r!=s[arr].r)
    {
        mark=0;
        return 0;
    }
    ll res;
    node now=s[arr++];
    res=(C(now.r-now.l,now.id-now.l)*dfs(now.l,now.id-1))%mod;
    res=(res*dfs(now.id+1,now.r))%mod;
    return res;
}


int main()
{
    ////freopen("in.txt", "r", stdin);  
    int n,cas=1;
    init();
    IO::begin();  
    while(IO::read(n))
    {
        arr=1;
        for (int i = 1; i <= n; i++) IO::read(s[i].l);  
        for (int i = 1; i <= n; i++) IO::read(s[i].r), s[i].id = i;  
        sort(s+1,s+n+1,cmp);

        mark=1;
        printf("Case #%d: %lld\n",cas++,dfs(1,n) );
    }
}
posted @ 2017-09-19 21:18  黑码的博客  阅读(96)  评论(0编辑  收藏  举报