当前位置: 首页 > news >正文

Luogu P9221 「TAOI-1」Pentiment 题解 [ 蓝 ] [ 二维 DP ] [ 线段树优化 ] [ 珂朵莉树 ]

Pentiment:比较 EZ 的线段树优化,但是我调了两天才调完 /ll。

不难想出一个暴力 DP\(dp_{i,j}\) 表示直角蛇在第 \(i\) 行第 \(j\) 列进入第 \(i+1\) 行的方案数。然后转移是显然的:

  • 当这个格子被 ban,\(dp_{i,j} = 0\)
  • 否则,\(dp_{i,j}\xleftarrow[l < k < r]{+} \sum dp_{i - 1, k}\)

时间复杂度是 \(O(nm)\) 的,无法通过。

注意到 DP 转移的形式是一个区间覆盖,区间查询和的形式,所以直接上线段树转移即可。注意要特判空白行。

因为值域较大,所以可以离散化或者动态开点。时间复杂度 \(O(n\log n)\)

本题还存在线性做法,区间覆盖可以上珂朵莉树,快速幂可以使用光速幂代替,时间复杂度 \(O(n)\)。但我不会光速幂,于是下面的代码是采用离散化线段树实现的。

#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc (p << 1)
#define rc ((p << 1) | 1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi = pair<int, int>;
const int N = 200005;
const ll mod = 998244353;
ll n, m, q, x[N], y[N], b[N], bn;
map<int, vector<int> > tot;
struct Node{int l, r;ll len, sm, tag = -1;
};
struct Segtree{Node tr[4 * N];void pushup(int p){tr[p].sm = (tr[lc].sm + tr[rc].sm) % mod;}void pushdown(int p){if(tr[p].tag != -1){tr[lc].sm = tr[lc].len * tr[p].tag % mod;tr[rc].sm = tr[rc].len * tr[p].tag % mod;tr[lc].tag = tr[p].tag;tr[rc].tag = tr[p].tag;}tr[p].tag = -1;}void build(int p, int ln, int rn){tr[p] = {ln, rn, (b[rn + 1] - b[ln]) % mod, (b[rn + 1] - b[ln]) % mod, -1};if(ln == rn) return;int mid = (ln + rn) >> 1;build(lc, ln, mid);build(rc, mid + 1, rn);pushup(p);}void update(int p, int ln, int rn, ll v){if(ln <= tr[p].l && tr[p].r <= rn){tr[p].sm = v * tr[p].len % mod;tr[p].tag = v;return;}pushdown(p);int mid = (tr[p].l + tr[p].r) >> 1;if(ln <= mid) update(lc, ln, rn, v);if(rn >= mid + 1) update(rc, ln, rn, v);pushup(p);}ll query(int p, int ln, int rn){if(ln <= tr[p].l && tr[p].r <= rn) return tr[p].sm;pushdown(p);int mid = (tr[p].l + tr[p].r) >> 1;if(rn <= mid) return query(lc, ln, rn);if(ln >= mid + 1) return query(rc, ln, rn);return (query(lc, ln, rn) + query(rc, ln, rn)) % mod;}
}tr1;
int getid(int x)
{return (lower_bound(b + 1, b + bn + 1, x) - b);
}
ll qpow(ll a, ll b)
{ll res = 1;while(b){if(b & 1) res = (res * a) % mod;b >>= 1;a = (a * a) % mod;}return res;
}
int main()
{//freopen("sample.in", "r", stdin);//freopen("sample.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> m >> q;for(int i = 1; i <= q; i++){cin >> x[i] >> y[i];b[++bn] = y[i];b[++bn] = y[i] + 1;}b[++bn] = m + 1;b[++bn] = 1;sort(b + 1, b + bn + 1);bn = unique(b + 1, b + bn + 1) - b - 2;if(q == 0){cout << qpow(m, n + 1);return 0;}tr1.build(1, 1, bn);for(int i = 1; i <= q; i++)tot[x[i]].push_back(getid(y[i]));int pre = 0;for(auto itm : tot){int now = itm.fi;if(pre != now - 1){ll tmp = tr1.query(1, 1, bn);tmp = qpow(m, now - 2 - pre) * tmp % mod;tr1.update(1, 1, bn, tmp);}int nxt = 0;for(auto id : itm.se){if(nxt + 1 <= id - 1)tr1.update(1, nxt + 1, id - 1, tr1.query(1, nxt + 1, id - 1) * (now >= 0 ? 1 : b[id - 1] - b[nxt]) % mod);tr1.update(1, id, id, 0);nxt = id;}if(nxt + 1 <= bn)tr1.update(1, nxt + 1, bn, tr1.query(1, nxt + 1, bn) * (now >= 0 ? 1 : m - b[nxt]) % mod);pre = now;}ll ans = tr1.query(1, 1, bn);ans = qpow(m, n - pre) * ans % mod;cout << ans;return 0;
}
http://www.sczhlp.com/news/25172/

相关文章:

  • 优化设计六年级下册语文答案重庆网站seo建设哪家好
  • 西安做网站公司怎么样个人接外包项目平台
  • 网站的建设需要多少企业网络推广方法
  • 哈尔滨手机网站建设现在做百度快速收录的方法
  • 利用css技术做网站的思路seo百度关键字优化
  • hang.zhang
  • 网站建设技术是干嘛的百度搜索提交入口
  • 网站模板 使用百度做广告费用
  • 开发平台 华为长沙网站托管seo优化公司
  • 网站被模仿如何维权阿里云域名注册入口官网
  • wordpress百科晨阳seo服务
  • 怎么提升网站的流量吗凡科建站怎么用
  • 珠海做网站哪家专业自然搜索优化
  • 小额贷款网站怎么做互联网媒体推广
  • 延安网站建设网络公司淘宝运营培训
  • 指针详解4
  • Cloud code -Windows安装cloud code
  • 搭建MySQL主从
  • 张家界做网站找哪家好网站是否含有seo收录功能
  • 便捷的邢台做网站市场监督管理局是干什么的
  • 山西汽车网站建设公司市场营销策划方案
  • 淮南网站建设好100个免费推广网站
  • 购物网站创业时是如何做宣传的怎么免费搭建自己的网站
  • 帮企业做网站的公司最近国家新闻
  • 网站 的版面结构网站的优化和推广方案
  • 优秀网站页面设计图片营销是什么
  • 网站官网怎么做网站快速收录工具
  • 8.21
  • Luogu P12847 [蓝桥杯 2025 国 A] 斐波那契数列 题解 [ 蓝 ] [ 矩阵加速 ] [ 扩展欧拉定理 ]
  • Windows快速删除大量小文件目录