zoukankan      html  css  js  c++  java
  • 51nod 1218 最长递增子序列 V2——LIS+思路(套路)

    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1218

    自己怎么连这种 喜闻乐见的大水题 都做不出来了……

    好像见过的套路,就是求每个位置到它为止的LIS和从它开始的LIS,最后拼起来是ans+1的就在LIS上。

    然后试图通过方案数来判断经过该位置的LIS有多少,以判断该位置是不是唯一的。

    WA了一次后发现自己的树状数组传参没有-1,求成非严格的了。

    还是WA了后面的点。给方案数开了long long后多A了几个点,但还是不能AC。尝试取模,通过的点数和没开long long一样。

    然后去看题解。

    ……

    原来只要稍加分析就能得出可从长度的唯一性来判断。自己还是思考太少,动手太匆忙……

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=5e4+15,fx=5,mod=998244353;
    int n,m,a[N],tp[N],f[N],len[N],cd[N],ans,cnt[N];
    //int g[N],p[N],c[N],prn;
    int rdn()
    {
      int ret=0,fx=1; char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-') fx=-1; ch=getchar();}
      while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return ret*fx;
    }
    void upd(int &x){x-=(x>=mod?mod:0);}
    void query(int x,int &l/*,int &k*/)
    {
      for(;x>0+fx;x-=(x&-x))
        {
          if(f[x]>l)
        {
          l=f[x];
          // k=g[x];
        }
          //      else if(f[x]==l) k+=g[x],upd(k);
        }
    }
    void add(int x,int l/*,int k*/)
    {
      for(;x<=m+fx;x+=(x&-x))
        {
          if(l>f[x])
        {
          f[x]=l;
          // g[x]=k;
        }
          //      else if(l==f[x]) g[x]+=k,upd(g[x]);
        }
    }
    int main()
    {
      n=rdn();
      for(int i=1;i<=n;i++) a[i]=tp[i]=rdn();
      sort(tp+1,tp+n+1); m=unique(tp+1,tp+n+1)-tp-1;
      for(int i=1;i<=n;i++) a[i]=lower_bound(tp+1,tp+n+1,a[i])-tp;
      for(int i=n;i;i--)
        {
          query(m-a[i]+fx,len[i]/*,p[i]*/);//not +1 for yan ge
          //      if(!len[i]) p[i]=1; 
          len[i]++;
          add(m-a[i]+1+fx,len[i]/*,p[i]*/);
          if(len[i]>ans){ans=len[i];/*prn=p[i];*/}
          //      else if(len[i]==ans) prn+=p[i],upd(prn);
        }
      memset(f,0,sizeof f);
      //  memset(g,0,sizeof g);
      for(int i=1;i<=n;i++)
        {
          query(a[i]-1+fx,cd[i]/*,c[i]*/);//a[i]-1!!!
          //      if(!cd[i]) c[i]=1;
          cd[i]++;
          if(len[i]+cd[i]==ans+1)cnt[cd[i]]++;
          add(a[i]+fx,cd[i]/*,c[i]*/);
        }
      printf("A:");
      for(int i=1;i<=n;i++)
        if(len[i]+cd[i]==ans+1&&cnt[cd[i]]>1/*&&(ll)p[i]*c[i]%mod<prn*/)
          printf("%d ",i);
      printf("
    ");
      printf("B:");
      for(int i=1;i<=n;i++)
        if(len[i]+cd[i]==ans+1&&cnt[cd[i]]==1/*&&(ll)p[i]*c[i]%mod==prn*/)
          printf("%d ",i);
      printf("
    ");
      return 0;
    }
  • 相关阅读:
    _I、_O、_IO的含义
    ARM启动代码中_main 与用户主程序main()的区别
    ARM汇编程序中的伪指令
    oracle密码过期问题
    等待界面-调转页面前button篇
    等待效果
    winfrom中Application.Restart()
    自动刷新处理
    泛微E8二次开发
    我的菜园子
  • 原文地址:https://www.cnblogs.com/Narh/p/9642994.html
Copyright © 2011-2022 走看看