2017 多校训练第一场 HDU 6044 Limited Permutation

来源:互联网 发布:手动安装windows补丁 编辑:程序博客网 时间:2024/04/27 04:24
题意:有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])


题解:
首先要理解题意:当前仅当li<=L<=i<=R<=ri时P[i]=min(P[L],P[L+1],...,P[R])
因此对于P[i]一定有P[i]>P[li-1]且P[i]>P[ri+1],进一步说区间[li,ri](除了[1,n])一定被某个区间[lj,rj]包含,且j=li-1或j=ri+1
即区间j可分成[lj,j-1]和[j+1,rj]


我们把n个区间按L升序R降序进行排序(这样得到的区间LR正是前序遍历的区间)。得到的第1个区间一定要是[1,n](1比任何数都小),否则不合法,输出0;设这个区间对应的是第i个数,因此区间可再分为[1,i-1]和[i+1,n],看是否有这2个区间,如果没有则不合法,输出0...直到区间不可再分。


现在再来考虑方法数:设f(i)为区间i内的方法数,u,v分别为左右子区间,i内一共有ri-li+1个数,除去中间一个,要从中选i-li个数放入左区间,剩下的放入右区间,因此答案为:f(u)*f(v)*C(ri-li,i-li)
#include <bits/stdc++.h>// #define test TEST using namespace std;const int mod=1e9+7;const int maxn=1e6+6;typedef long long ll;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;      }  } typedef struct Node{int l,r,id;bool operator < (const Node &a) const{if(l!=a.l) return l<a.l;else return r>a.r;}}node;node seg[maxn];ll fac[maxn],inv[maxn];ll Power_Mod(ll a,ll b){ll ans=1;while(b){if(b&1ll){ans=ans*a%mod;}a=a*a%mod;b>>=1;}return ans;}void init(){fac[0]=1;for(int i=1;i<maxn;i++){fac[i]=fac[i-1]*i%mod;}inv[1]=1;for(int i=2;i<maxn;i++){inv[i]=(mod-mod/i)*inv[mod%i]%mod;}inv[0]=1;for(int i=1;i<maxn;i++){inv[i]=inv[i-1]*inv[i]%mod;}}ll C(ll a,ll b){return fac[a]*inv[b]%mod*inv[a-b]%mod;}// void init() {  //     fac[0] = 1;  //     for (int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * i % mod;  //     inv[maxn - 1] = Power_Mod(fac[maxn - 1], mod - 2);  //     for (int i = maxn - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod;  // }  // ll C(ll n, ll m) {  //     ll ret = 1;  //     while (n && m) {  //         ll nn = n % mod, mm = m % mod;  //         if (nn < mm) return 0;  //         ret = ((ret * fac[nn] % mod) * inv[mm] % mod) * inv[nn - mm] % mod;  //         n /= mod, m /= mod;  //     }  //     return ret;  // } int flag,rear;ll dfs(int l,int r){if(!flag) return 0;if(l>r) return 1;if(seg[rear].l!=l || seg[rear].r!=r){flag=0;return 0;}node now=seg[rear++];ll ret=C(now.r-now.l,now.id-now.l)*dfs(now.l,now.id-1)%mod;ret=(ret*dfs(now.id+1,now.r))%mod;return ret;}int main(int argc, char const *argv[]){#ifdef testfreopen("test.txt","r",stdin);#endif init();IO::begin();int cas=1,n;while(IO::read(n)){for(int i=1;i<=n;i++) {seg[i].id=i;IO::read(seg[i].l);}for(int i=1;i<=n;i++) IO::read(seg[i].r);sort(seg+1,seg+n+1);flag=rear=1;printf("Case #%d: %lld\n",cas++,dfs(1,n));}return 0;}

原创粉丝点击