zoukankan      html  css  js  c++  java
  • CF1474F 1 2 3 4 ...

    还是之前做的题。。还是一样的毫无印象。。。我是SB

    给的(x)是没有用的。

    最长上升子序列的长度可以直接枚举起点终点(O(n^2))求解。困难的是计数部分。

    找出序列中所有的极长段使得开头至结尾能形成最长上升子序列。

    (就是每一段开头结尾最小值和最大值都在减小)

    对于每一个极长段分别求解。

    暴力DP就是(dp_{v,i})表示当前值(v),当前所在段为(i)的方案数。

    优化再一次用到了apio划艇和noi机器人的把值域分段的技巧。。然而我还是没掌握

    就是升序枚举值域段,有一些段合法且转移相同,用矩阵快速幂优化。

    这个做法还得把(0)全都删掉还有特判全是负数的情况。。

    时间复杂度(O(n^4log A))

    感觉自己还是说不明白。。看代码吧,我真的太菜了

    #include <bits/stdc++.h>
    using namespace std;
    #define fp(i,l,r) for(register int (i)=(l);(i)<=(r);++(i))
    #define fd(i,l,r) for(register int (i)=(l);(i)>=(r);--(i))
    #define fe(i,u) for(register int (i)=front[(u)];(i);(i)=e[(i)].next)
    #define mem(a) memset((a),0,sizeof (a))
    #define O(x) cerr<<#x<<':'<<x<<endl
    #define int long long
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    void wr(int x){
    	if(x<0)putchar('-'),x=-x;
    	if(x>=10)wr(x/10);
    	putchar('0'+x%10);
    }
    const int MAXN=52,mod=998244353;
    inline void tmod(int &x){x%=mod;}
    int n,tot,a[MAXN],ans,sum,res,m,L[MAXN],R[MAXN],sta[MAXN*2],top;
    struct mat{
    	int a[MAXN][MAXN];
    	inline mat operator*(const mat &b)const{
    		mat c;fp(i,0,m)fp(j,0,m)c.a[i][j]=0;
    		fp(k,0,m)fp(i,0,m)fp(j,0,m)tmod(c.a[i][j]+=a[i][k]*b.a[k][j]);
    		return c;
    	}
    };
    inline mat qpow(mat a,int b){
    	mat c;fp(i,0,m)fp(j,0,m)c.a[i][j]=0;
    	fp(i,0,m)c.a[i][i]=1;
    	for(;b;b>>=1,a=a*a)
    	if(b&1)c=c*a;
    	return c;
    }
    inline int calc(int l,int r){
    	m=r-l+1;tot=0;int s=0;
    	fp(i,l,r){
    		++tot;
    		L[tot]=(s+(a[i]<0?-1:1));R[tot]=s+a[i];
    		s+=a[i];
    	}
    	top=0;L[1]=0;
    	fp(i,1,m){
    		sta[++top]=min(L[i],R[i]);sta[++top]=max(L[i],R[i])+1;
    	}
    	sort(sta+1,sta+1+top);top=unique(sta+1,sta+1+top)-sta-1;
    	mat ans,tmp;
    	fp(i,0,m)fp(j,0,m)ans.a[i][j]=0;ans.a[0][0]=1;
    	fp(kk,1,top-1){
    		int l=sta[kk],r=sta[kk+1]-1;
    		fp(i,0,m)fp(j,0,m)tmp.a[i][j]=0;
    		fp(i,1,m)if(min(L[i],R[i])<=l&&max(L[i],R[i])>=r){
    			if(L[i]<R[i])fp(j,0,i)tmp.a[j][i]=1;
    			else fp(j,0,i-1)tmp.a[j][i]=1;
    		}
    		ans=ans*qpow(tmp,r-l+1);
    	}
    	int ss=0;
    	fp(i,0,m)tmod(ss+=ans.a[0][i]);
    	return ss;
    }
    main(){
    	n=read();read();
    	fp(i,1,n){
    		int t=read();
    		if(t)a[++tot]=t;
    	}
    	n=tot;
    	fp(i,1,n){
    		int t=sum;
    		fp(j,i,n){
    			t+=a[j];
    			ans=max(ans,t-sum);
    		}
    		sum+=a[i];
    	}
    	if(!ans){
    		int t=1;
    		fp(i,1,n)tmod(t-=a[i]);
    		printf("1 %lld
    ",t);
    		return 0;
    	}
    	fp(i,1,n){
    		int t=0,p=0;
    		fp(j,i,n){
    			t+=a[j];
    			if(t==ans){
    				p=j;//you can't break here!
    			}
    		}
    		if(p)tmod(res+=calc(i,p)),i=p;
    	}
    	printf("%lld %lld
    ",ans+1,res);
    	return 0;
    }
    
  • 相关阅读:
    clickhouse集群部署
    zookeeper集群部署
    linux下安装多路径multipath
    采用xtrabackup部署主从同步(生产)
    部署dg备库同步ogg
    goldengate同步(主库rac从库单节点)
    python3发送邮件
    python2发送邮件
    pip版本过高导致报错
    ERROR 1558 (HY000): Column count of mysql.user is wrong
  • 原文地址:https://www.cnblogs.com/WinterSpell/p/14932811.html
Copyright © 2011-2022 走看看