zoukankan      html  css  js  c++  java
  • [TJOI2014] 上升子序列

        刚刚做的时候一看:这不是个傻逼题吗hhhhh。。。。然后发现写完了过不了样例,仔细一看题:同构的算一种。

        这可咋办啊?

        其实很简单,设f[i] 为 以a[i] 结尾的上升子序列个数,我们考虑当前如果算到 i 了,那么我们需要查询 a[j] < a[i] 且 j < i 的所有 的 f[j] 的和。

        为了避免重复计算,我们只需要保留每个权值的j最大的那个就行了,因为那个 j 肯定可以包含之前的所有答案。

        

        所以我们边计算边维护即可。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100005,ha=1000000007;
    inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
    int a[maxn],num[maxn],ky,n,f[maxn],ans,g[maxn],pre[maxn];
    inline void update(int x,int y){ for(;x<=ky;x+=x&-x) f[x]=add(f[x],y);}
    inline int query(int x){ int an=0; for(;x;x-=x&-x) an=add(an,f[x]); return an;}
    int main(){
    //	freopen("data.in","r",stdin);
    //	freopen("data.out","w",stdout);
    	
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",a+i),num[i]=a[i];
    	sort(num+1,num+n+1);
    	ky=unique(num+1,num+n+1)-num-1;
    	for(int i=1;i<=n;i++) a[i]=lower_bound(num+1,num+ky+1,a[i])-num;
    	
    	for(int i=1;i<=n;i++){
    		if(pre[a[i]]) update(a[i],ha-pre[a[i]]);
    		g[i]=add(query(a[i]-1),1),update(a[i],g[i]);
    		pre[a[i]]=g[i];
    	}
    	
    	for(int i=1;i<=ky;i++) if(pre[i]) ans=add(ans,pre[i]-1);
    	
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    [译]git reflog
    [译]git rebase -i
    [译]git rebase
    [译]git commit --amend
    [译]git clean
    [译]git reset
    [译]git revert
    [译]git checkout
    [译]git log
    [译]git status
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8962836.html
Copyright © 2011-2022 走看看