zoukankan      html  css  js  c++  java
  • [CC-MCO16306]Fluffy and Alternating Subsequence

    [CC-MCO16306]Fluffy and Alternating Subsequence

    题目大意:

    给定一个(1sim n(nle3 imes10^5))的排列(a)
    对于一个序列(b),如果以下两个条件之一成立,则称(b_i)是一个跳跃序列:

    1. (b_{2k}<b_{2k-1})对所有的(2kle n)都成立,且(b_{2k}<b_{2k+1})对所有的(2k+1le n)都成立。
    2. (b_{2k}>b_{2k-1})对所有的(2kle n)都成立,且(b_{2k}>b_{2k+1})对所有的(2k+1le n)都成立。

    (a)的最长跳跃子序列的长度(l),并求出有多少个长度为(l)的跳跃子序列,模(10^9+7)

    思路:

    (f[i][0/1][0/1])表示考虑到第(i)位,当前位是峰/谷,当前序列符合条件1/2时,长度的最大值。(g[i][0/1][0/1])表示相同状态下的方案数。

    线段树优化后做做到(mathcal O(nlog n))

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=3e5+1,mod=1e9+7;
    int a[N],f[N][2][2],g[N][2][2];
    class SegmentTree {
    	#define _left <<1
    	#define _right <<1|1
    	#define mid ((b+e)>>1)
    	private:
    		int f[N<<2],g[N<<2];
    		void push_up(const int &p) {
    			f[p]=std::max(f[p _left],f[p _right]);
    			g[p]=0;
    			if(f[p _left]==f[p]) (g[p]+=g[p _left])%=mod;
    			if(f[p _right]==f[p]) (g[p]+=g[p _right])%=mod;
    		}
    	public:
    		void modify(const int &p,const int &b,const int &e,const int &x,const int &y,const int &z) {
    			if(b==e) {
    				if(y>f[p]) {
    					f[p]=y;
    					g[p]=0;
    				}
    				if(y==f[p]) {
    					(g[p]+=z)%=mod;
    				}
    				return;
    			}
    			if(x<=mid) modify(p _left,b,mid,x,y,z);
    			if(x>mid) modify(p _right,mid+1,e,x,y,z);
    			push_up(p);
    		}
    		std::pair<int,int> query(const int &p,const int &b,const int &e,const int &l,const int &r) {
    			if(b==l&&e==r) {
    				return std::make_pair(f[p],g[p]);
    			}
    			std::pair<int,int> pl,pr,ret;
    			pl=std::make_pair(0,0);
    			pr=std::make_pair(0,0);
    			ret=std::make_pair(0,0);
    			if(l<=mid) pl=query(p _left,b,mid,l,std::min(mid,r));
    			if(r>mid) pr=query(p _right,mid+1,e,std::max(mid+1,l),r);
    			if(pl.first>ret.first) {
    				ret=std::make_pair(pl.first,0);
    			}
    			if(pl.first==ret.first) {
    				(ret.second+=pl.second)%=mod;
    			}
    			if(pr.first>ret.first) {
    				ret=std::make_pair(pr.first,0);
    			}
    			if(pr.first==ret.first) {
    				(ret.second+=pr.second)%=mod;
    			}
    			return ret;
    		}
    	#undef _left
    	#undef _right
    	#undef mid
    };
    SegmentTree sgt[2][2];
    int main() {
    	const int n=getint();
    	for(register int i=1;i<=n;i++) {
    		a[i]=getint();
    	}
    	for(register int i=1;i<=n;i++) {
    		f[i][0][1]=f[i][1][1]=1;
    		g[i][0][1]=g[i][1][1]=1;
    		for(register int j=0;j<2;j++) {
    			for(register int k=0;k<2;k++) {
    				std::pair<int,int> p;
    				if(j) {
    					p=sgt[!j][!k].query(1,1,n,a[i],n);
    				} else {
    					p=sgt[!j][!k].query(1,1,n,1,a[i]);
    				}
    				if(p.first+1>f[i][j][k]) {
    					f[i][j][k]=p.first+1;
    					g[i][j][k]=0;
    				}
    				if(p.first+1==f[i][j][k]) {
    					(g[i][j][k]+=p.second)%=mod;
    				}
    			}
    		}
    		for(register int j=0;j<2;j++) {
    			for(register int k=0;k<2;k++) {
    				sgt[j][k].modify(1,1,n,a[i],f[i][j][k],g[i][j][k]);
    			}
    		}
    	}
    	int ans=0,cnt=0;
    	for(register int i=1;i<=n;i++) {
    		for(register int j=0;j<2;j++) {
    			for(register int k=0;k<2;k++) {
    				ans=std::max(ans,f[i][j][k]);
    			}
    		}
    	}
    	for(register int i=1;i<=n;i++) {
    		for(register int j=0;j<2;j++) {
    			for(register int k=0;k<2;k++) {
    				if(f[i][j][k]==ans) {
    					(cnt+=g[i][j][k])%=mod;
    				}
    			}
    		}
    	}
    	printf("%d %d
    ",ans,cnt);
    	return 0;
    }
    
  • 相关阅读:
    java算法----------常用的加密算法
    java多线程---------java.util.concurrent并发包----------等待多线程完成
    java多线程---------java.util.concurrent并发包----------ThreadPoolExecutor
    java多线程---------java.util.concurrent并发包
    一头扎进Spring之---------Spring核心容器----------
    深入理解java集合框架之---------Linked集合 -----构造函数
    深入理解java集合框架之---------Arraylist集合 -----添加方法
    深入理解java集合框架之---------Arraylist集合 -----构造函数
    深入理解java集合框架之---------HashMap集合
    linux输出与查看的几种方式
  • 原文地址:https://www.cnblogs.com/skylee03/p/9876317.html
Copyright © 2011-2022 走看看