zoukankan      html  css  js  c++  java
  • 【洛谷3336】[ZJOI2013] 话旧(DP)

    点此看题面

    大致题意: 给定一个在([0,m])中连续的分段函数,其中(f(0)=f(m)=0),每一个极小值都为(0),且对于任意([0,m-1])范围内的整数(i)(f(x))([i,i+1])一段上斜率为(1)(-1)。现给定函数图像上若干个点,求符合条件的函数个数,以及函数最大值的最大值。

    (DP)

    我们设(f_{i,0/1})表示考虑到第(i)个点,从(a_i-1)(a_i)的直线是上升/下降的方案数。

    假设当前考虑从(A)点到(B)点的一个转移,可以借助下面这张图进行理解:

    我们先找出(A)点向右下、(B)点向左下与(x)轴的交点,设两交点间距离为(2k)(可以证明一定是偶数)。

    考虑两个交点之间可以一上一下一上一下地乱跳,这一方案其实就是(k)个物品分成任意段的方案数,那么只要判断每个物品是否与前一个物品是否在同一段中,方案数为(2^{k-1})

    首先我们发现,如果到(B)点的直线向上,那么就如图中实线部分所示。否则,如果到(B)点的直线向下,我们只要把图中绿色部分移到(B)的左上方(如绿色虚线部分所示)。可见,两者转移其实是一样的。

    其次,如果到(A)的直线向下,那么就如图中实线部分所示。否则,(A)点可以直接向下,也可以把图中的黄色部分移到(A)的右上方(如黄色虚线部分所示),转移时还要额外乘上(2)

    用式子表示也就是:

    [f_{i,0}=f_{i,1}=2^k imes f_{i-1,0}+2^{k-1} imes f_{i-1,1} ]

    但在实际转移的过程中,还需要注意两点连线恰好是一条斜率为(1)(-1)的直线以及(kle0)的特殊情况,这里就不给出转移方程了,直接见代码吧。

    还有,关于第二问的最大值,显然是个非常智障的东西吧。。。((Upt):好吧,智障的是我,原来的写法被(Hack)了)

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000000
    #define X 19940417
    #define Gmax(x,y) (x<(y)&&(x=(y)))
    using namespace std;
    int n,m,a[N+5],b[N+5],f[N+5][2];map<int,int> p;map<int,int>::iterator it;
    I int QP(RI y=1) {RI x=2,t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    }F;
    int main()
    {
    	RI i,t,x,y;for(F.read(m),F.read(t),i=1;i<=t;++i) F.read(x),F.read(y),p[x]=y;
    	for(p[0]=p[m]=0,it=p.begin();it!=p.end();++it) a[++n]=it->first,b[n]=it->second;//用map去重并排序
    	RI Mx=0,k;for(f[1][1]=1,i=2;i<=n;++i) g=0,
    		a[i]-a[i-1]==b[i]-b[i-1]?f[i][0]=(f[i-1][0]+(b[i-1]?0:f[i-1][1]))%X://两点连线斜率为1
    		(
    			a[i]-a[i-1]==b[i-1]-b[i]?f[i][1]=(f[i-1][0]+f[i-1][1])%X://两点连线斜率为-1
    			(
    				(k=((a[i]-b[i])-(a[i-1]+b[i-1]))/2)<0?f[i][1]=f[i-1][0],g=1://k<0,只能在上空转移
    				(
    					!k?f[i][0]=(f[i-1][0]+f[i-1][1])%X,f[i][1]=f[i-1][0]://k=0,向上向下都只有一种方式
    						(t=QP(k-1),f[i][0]=f[i][1]=(2LL*f[i-1][0]*t+1LL*f[i-1][1]*t)%X,g=1)//一般情况
    				)
    			)
    		),!b[i]&&(f[i][0]=0),//若纵坐标为0,不可能出现向上的情况,清零
    		g?Gmax(Mx,(a[i]+b[i]-a[i-1]+b[i-1])/2):Gmax(Mx,max(b[i-1],b[i]));//统计最大值
    	return printf("%d %d
    ",f[n][1],Mx),0;
    }
    
  • 相关阅读:
    BZOJ3420[POI2013]Triumphal arch&BZOJ5174[Jsoi2013]哈利波特与死亡圣器——树形DP+二分答案
    BZOJ3417[Poi2013]Tales of seafaring——BFS
    BZOJ3750[POI2015]Pieczęć——链表
    bzoj 3594 方伯伯的玉米田
    Cocos2dx学习之SimpleGame
    新旧版本的quick-x项目移植
    cocos2dx 2.2.1 下面创建新项目测试运行
    VS2012下面编译Cocos2dx的HelloLua项目时报错>>> 项目文件"" 已被重命名或已不在解决方案中
    cocos2dx-lua or quick 2dx 中的图片资源加密
    关于对quick-2dx项目中的Lua代码的加密
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3336.html
Copyright © 2011-2022 走看看