zoukankan      html  css  js  c++  java
  • CSU 1807: 最长上升子序列~ 分类讨论

    1807: 最长上升子序列~

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 138  Solved: 17
    [Submit][Status][Web Board]

    Description

    Bobo 在 ICPCCamp 学会了解决最长上升子序列问题后得到了一个长度为 n 的数列 p1,p2,…,pn.
    Bobo 想用 1,2,…,n 来替换其中值为 0 的元素,使得 p1,p2,…,pn 互不相同(即 p1,p2,…,pn 是 {1,2,…,n} 的排列)。
    现在 Bobo 想知道,替换后最长上升子序列的长度恰好为 (n-1) 数列的数量。

    Input

    输入包含不超过 300 组数据,其中不超过 20 组的 n 超过 100.
    每组数据的第一行包含一个整数 n (1≤n≤105).
    第二行包含 n 个整数p1,p2,…,pn  (0≤pi≤n).
    保证p1,p2,…,pn中非 0 的元素互不相同。

    Output

    对于每组数据,输出一个整数表示要求的值。

    Sample Input

    3
    0 0 0
    4
    0 0 0 0
    5
    1 0 0 4 5
    

    Sample Output

    4
    9
    1
    

    HINT

    Source

    [Submit][Status][Web Board]

    分析:就是大分类讨论,考虑偏移

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int N = 1e5 + 5;
    const double eps = 1e-9;
    const double INF = 1e12;
    int n,a[N],b[N],m[N];
    void solve3(int id){
       memset(b,0,sizeof(b));
       b[id] = a[id];int cnt=0;
       for(int i=1;i<=n;++i){
         if(i==id)continue;
         ++cnt;if(cnt==a[id])++cnt;
         b[i]=cnt;
       }
       for(int i=1;i<=n;++i)
        if(a[i]&&a[i]!=b[i]){
            puts("0");
            return;
        }
       puts("1"); 
    }
    void solve1(int id){
      if(a[id+1]==id){
         for(int i=1;i<=n;++i){
            b[i]=i;
         }
         swap(b[id],b[id+1]);
         for(int i=1;i<=n;++i){
           if(a[i]&&a[i]!=b[i]){
             puts("0");return;
           }
         }
         puts("1");
         return;
      }
      int r=id,flag=0;
      for(int i=id+1;i<=n;++i){
        if(a[i] == 0)continue;
        if(i!=a[i]){
          if(!flag&&a[i]==i+1)r=i;
          else{
              puts("0");
              return;
          }
        }
        if(i==a[i])flag=1;
      }
      int t1 = 0,t2 = 0;
      for(int i= id-1;i&&a[i]==0;--i)++t1;
      for(int i=r+1;i<=n&&a[i]==0;++i)++t2;
      LL ret = 1ll*(t1+1)*t2;
      printf("%lld
    ",ret);
    }
    void solve2(int id){
       if(a[id-1]==id){
         for(int i=1;i<=n;++i){
            b[i]=i;
         }
         swap(b[id],b[id-1]);
         for(int i=1;i<=n;++i){
           if(a[i]&&a[i]!=b[i]){
             puts("0");return;
           }
         }
         puts("1");
         return;
      }
      int r=id,flag=0;
      for(int i=id+1;i<=n;++i){
        if(a[i]==0)continue;
        if(i!=a[i]){
          if(!flag&&a[i]==i-1)r=i;
          else{
             puts("0");
             return;
          }
        }
        if(i==a[i])flag=1;
      }
      int t1 = 0,t2 = 0;
      for(int i=id-1;i&&a[i]==0;--i)++t1;
      for(int i=r+1;i<=n&&a[i]==0;++i)++t2;
      LL ret = 1ll*(t2+1)*t1;
      printf("%lld
    ",ret);
    }
    int main(){
      while(~scanf("%d",&n)){
        memset(m,-1,sizeof(m));
        for(int i=1;i<=n;++i)scanf("%d",&a[i]),m[a[i]]=i;
        bool flag = false;
        for(int i=1;i<=n;++i){
          if(a[i]&&(a[i]-i>1||i-a[i]>1)){
             solve3(i);
             flag = true;
             break;
          }
        }
        if(flag)continue;
        for(int i=1;i<=n;++i){
          if(a[i]==0||a[i]==i)continue;
          if(a[i]-i==1)solve1(i);
          else if(i-a[i]==1)solve2(i);
          flag = true;
          break;
        }
        if(flag)continue;
        int cnt=0;LL ret=0;
        for(int i=1;i<=n;++i){
          if(a[i]==0)++cnt;
          else if(cnt){
            ret+=1ll*(cnt-1)*(cnt-1);
            cnt=0;
          }
        }
        if(cnt)ret+=1ll*(cnt-1)*(cnt-1);
        printf("%lld
    ",ret);
      }
      return 0;
    }
    View Code
  • 相关阅读:
    pandas
    CTC Loss原理
    CTC 的工作原理
    Demystifying JavaScript Closures, Callbacks and IIFEs
    Css compatibility
    Flexbox——快速布局神器
    centos wordpress
    Encog
    D3js
    Lucene学习
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5845093.html
Copyright © 2011-2022 走看看