P3336 [ZJOI2013]话旧 题解
P3336 [ZJOI2013]话旧 题解
目前最优解 / 55ms
\texttt{0x01} 形式化题意
自己看,懒得写。
反正就是只要开始往下走了就一定要走到
\texttt{0x02} 思路
把所有给过的点排个序,相邻的每两个点计算方案数,发现对之前的计算结果影响很小,故考虑
考虑到当前点向上向下走会对结果产生影响(就是形式化题意里面说的),因此将当前点向上 / 向下加入状态,于是我们设:
别忘了sort & unique。
对于两个相邻的点
显然的,当
因此题目中默认
那就只能上升啦?
能不能由下降转为上升?
只要前面那个点
上升下降都可以啦。
你要想一下:如果按照贪心的思路一直向下,能不能碰到最底下?
为什么要这么想呢?
如果不能碰到:只能在上面出现拐点,且拐点 & 路径唯一。
这很好想叭。要是开始往下就不能回头了。其他地方必定会错过那个点。
如果刚好碰到:上面下面两条路,均唯一。
如果很早就能碰到:好多好多好多好多好多好多
接着分类讨论。那么如何区分这几种情况呢?
注意到我们画的图:两个点总是尽可能向下走与
一般的,对于
这就是分类讨论的依据。
和上面类似,自己想。
和上面类似,懒得写。
观察可以发现,
每次选定一个“齿”,将其往上翻,我们都可以得到一条新的路径。
设方案数为
如果初始点为上升:
如果初始点为下降:
\texttt{0x04 Q2}
第二问的话,贪心就好啦。
但是如果正在往下走的话贪心会寄。判断一下。
\texttt{0x05 Code}
代码美学。
int main()
{
read(n, m);
F(i, 1, m) P[i].input();
P[++ m].input(0, 0), P[++ m].input(n, 0);
sort(P + 1, P + m + 1); m = unique(P + 1, P + m + 1) - P - 1;
g[1] = 1;
F(i, 2, m)
{
int l = b.x - b.y - a.x - a.y >> 1;
if(a.x - b.x == a.y - b.y) f[i] = (f[i - 1] + (a.y ? 0 : g[i - 1])) % mod;
else if(a.x - b.x == b.y - a.y) g[i] = (f[i - 1] + (g[i - 1])) % mod;
else if(l < 0) g[i] = (f[i - 1] + (a.y ? 0 : g[i - 1])) % mod;
else if(l == 0) f[i] = (f[i - 1] + (g[i - 1])) % mod,
g[i] = (f[i - 1] + (a.y ? 0 : g[i - 1])) % mod;
else
{
int k = fastpow(2, l - 1, mod);
if(b.y) f[i] = 1ll * ((f[i - 1] << 1) + g[i - 1]) * k % mod;
g[i] = 1ll * ((f[i - 1] << 1) + g[i - 1]) * k % mod;
}
if(g[i] || !b.y) ans = qmax(ans, b.y, b.x + b.y - a.x + a.y >> 1);
}
write(' ', g[m], ans);
return 0;
}
三目运算符要是再不打括号
awa 就吃了自己吧。