PKUSC2019 D1T1 题解
前言
五一网课的例题,但是网上没有详细的题解(其实就是都没放代码),所以来写一篇,就当攒 RP 了。题目可以在这里(不强制在线)或这里(强制在线)提交。
题目简述
有
现在政府要建立
政府每年建设一个哨卡。人们好奇,对于前
由于 yzh 喜欢在线的算法,所以她想让你每年立马告诉她答案哦。
题目分析
先观察样例:
样例 #1
样例输入 #1
10 8 9 10 7 3 1 5 8 6 2 4 5 1 7 2 3 4 8 9
样例输出 #1
15 18 23 26 28 29 31 31
只有第一天
好像可以把两边都先排个序,不用花费:
然后先让第
然后再让第
然后再让第
然后再让第
总花费
再仔细看,要走到
其实这就是结论:答案等于经过了任何一个哨卡的逆序对个数。接下来考虑证明它。
任意一对逆序对必然要交换一次,如果一对逆序对中间跨过了一个哨卡,必然需要花费代价,因此答案至少是这个。
将两个关卡之间的部分排序,任意一对逆序对只会在相邻的时候交换一次,交换了所有逆序对即表明它走到了终点,因此答案至多是这个。
以上可以说是这题核心思考了。接下来就可以写出暴力代码了:
read(n, m); for (int i = 1; i <= n; ++i) read(p[i]); for (int i = 1; i <= m; ++i){ int x; read(x), mark[x] = true; long long res = 0; for (int a = 1; a <= n; ++a) for (int b = a + 1; b <= n; ++ b){ if (p[a] > p[b]){ bool flag = false; for (int x = a; x <= b - 1; ++x) if (mark[x]){ flag = true; break; } res += flag; } } write(res, '\n'); }
时间复杂度
代码
当然肯定要放代码的。
离线
//#pragma GCC optimize(3) //#pragma GCC optimize("Ofast", "inline", "-ffast-math") //#pragma GCC target("avx", "sse2", "sse3", "sse4", "mmx") #include <iostream> #include <cstdio> #define debug(a) cerr << "Line: " << __LINE__ << " " << #a << endl #define print(a) cerr << #a << "=" << (a) << endl #define file(a) freopen(#a".in", "r", stdin), freopen(#a".out", "w", stdout) #define main Main(); signed main(){ return ios::sync_with_stdio(0), cin.tie(0), Main(); } signed Main using namespace std; int n, m, p[500010], q[500010]; long long ans[500010]; bool mark[500010]; struct Bit_Tree{ constexpr inline int lowbit(const int x){ return x & -x; } int tree[500010]; void modify(int p, int v){ for (int i = p; i <= n; i += lowbit(i)) tree[i] += v; } int query(int p){ int res = 0; for (int i = p; i; i -= lowbit(i)) res += tree[i]; return res; } } yzh; struct DSU{ int fa[500010]; void init(){ for (int i = 1; i <= n; ++i) fa[i] = i; } int & operator [] (const int x) { return fa[x]; } int get(int x){ return fa[x] == x ? x : fa[x] = get(fa[x]); } } dsu; struct Segment_Tree{ struct node{ int lson, rson; int sum; } tree[500010 * 40]; int tot; void pushup(int idx){ tree[idx].sum = tree[tree[idx].lson].sum + tree[tree[idx].rson].sum; } int merge(int idx, int oidx, int l, int r, long long & ans){ if (!idx || !oidx) return idx | oidx; if (l == r) return tree[idx].sum += tree[oidx].sum, idx; int mid = (l + r) >> 1; ans += 1ll * tree[tree[idx].rson].sum * tree[tree[oidx].lson].sum; tree[idx].lson = merge(tree[idx].lson, tree[oidx].lson, l, mid, ans); tree[idx].rson = merge(tree[idx].rson, tree[oidx].rson, mid + 1, r, ans); return pushup(idx), idx; } void modify(int &idx, int l, int r, int p, int val){ if (l > p || r < p) return; if (!idx) tree[idx = ++tot].sum = 0; tree[idx].sum += val; if (l == r) return; int mid = (l + r) >> 1; modify(tree[idx].lson, l, mid, p, val); modify(tree[idx].rson, mid + 1, r, p, val); } } huan; int root[500010]; void init(){ // 获得初始答案,顺便初始化每一棵线段树 mark[0] = mark[n] = true; for (int i = 1; i <= m; ++i) mark[q[i]] = true; for (int i = 1, to; i <= n; i = to + 1){ for (to = i; ; ++to){ dsu[to] = i, huan.modify(root[i], 1, n, p[to], 1); ans[m + 1] += i - 1 - yzh.query(p[to]); if (mark[to]) break; } for (to = i; ; ++to){ yzh.modify(p[to], 1); if (mark[to]) break; } } } signed main(){ read(n, m); for (int i = 1; i <= n; ++i) read(p[i]); for (int i = 1; i <= m; ++i) read(q[i]); init(); for (int i = m; i >= 1; --i){ // 处理询问,线段树合并 q[i] q[i] + 1 int u = dsu.get(q[i]), v = dsu.get(q[i] + 1); root[u] = huan.merge(root[u], root[v], 1, n, ans[i]); dsu[v] = u, ans[i] = ans[i + 1] - ans[i]; } for (int i = 1; i <= m; ++i) write(ans[i + 1], '\n'); return 0; }
在线
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n, q, h[500010]; struct Yzh_Is_The_President{ struct node{ int lson, rson; int val; } tree[500010 * 30]; int root[500010], tot; void pushup(int idx){ tree[idx].val = tree[tree[idx].lson].val + tree[tree[idx].rson].val; } void build(int &idx, int l, int r){ tree[idx = ++tot] = {0, 0, 0}; if (l == r) return; int mid = (l + r) >> 1; build(tree[idx].lson, l, mid), build(tree[idx].rson, mid + 1, r); } void modify(int &idx, int oidx, int trl, int trr, int p, int v){ if (trl > p || trr < p) return; tree[idx = ++tot] = tree[oidx]; if (trl == trr) return tree[idx].val += v, void(); int mid = (trl + trr) >> 1; modify(tree[idx].lson, tree[oidx].lson, trl, mid, p, v); modify(tree[idx].rson, tree[oidx].rson, mid + 1, trr, p, v); pushup(idx); } int query(int lidx, int ridx, int trl, int trr, int l, int r){ if (trl > r || trr < l) return 0; if (l <= trl && trr <= r) return tree[ridx].val - tree[lidx].val; int mid = (trl + trr) >> 1; return query(tree[lidx].lson, tree[ridx].lson, trl, mid, l, r) + query(tree[lidx].rson, tree[ridx].rson, mid + 1, trr, l, r); } } yzh; struct Bit_Tree_Pre{ constexpr inline int lowbit(int x){ return x & -x; } int tree_min[500010], tree_max[500010]; inline void init(){ memset(tree_min, 0x3f, sizeof tree_min); } inline void modify(int p){ for (int i = p; i <= n; i += lowbit(i)) tree_max[i] = max(tree_max[i], p); for (int i = p; i; i &= i - 1) tree_min[i] = min(tree_min[i], p); } inline int query_min(int p){ int res = n + 1; for (int i = p; i <= n; i += lowbit(i)) res = min(res, tree_min[i]); return res; } inline int query_max(int p){ int res = 0; for (int i = p; i; i &= i - 1) res = max(res, tree_max[i]); return res; } } xym; long long ans; signed main() { read(n, q); yzh.build(yzh.root[0], 1, n); for (int i = 1; i <= n; ++i) read(h[i]), yzh.modify(yzh.root[i], yzh.root[i - 1], 1, n, h[i], 1); xym.init(), xym.modify(n); long long lastans = 736520, p; for (int i = 1; i <= q; ++i) { read(p), p ^= lastans; int l = xym.query_max(p) + 1, r = xym.query_min(p); int L = p - l + 1, R = r - p; if (L > R){ for (int x = p + 1; x <= r; ++x) if (h[x] < n) ans += yzh.query(yzh.root[l - 1], yzh.root[p], 1, n, h[x] + 1, n); } else { for (int x = l; x <= p; ++x) if (h[x] > 1) ans += yzh.query(yzh.root[p], yzh.root[r], 1, n, 1, h[x] - 1); } write(lastans = ans, '\n'); xym.modify(p); } return 0; }
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/18144269。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)