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

qoj.4878 Easy Problem 做题记录

高手。link

惯性思维很容易想到 Hall 定理 + 线段树 去处理,我一直想了 2h+,事实上有另外一种思路。

由于保留的所有区间都覆盖了位置 \(i\),我们考虑贪心做最大匹配:从左到右扫描每个位置,优先用 \(r\) 小的区间做匹配。

这样有个好处,我们可以把匹配的位置分为 \(\le i\)\(\ge i + 1\) 两部分,这两部分有很大的独立性。

我们考虑从左到右扫描线,从右到左进行贪心匹配(即优先匹配 \(l\) 更大的区间)。考虑 \(\ge i + 1\) 的部分,根据 Hall 定理判定匹配的合法性,开一棵线段树维护每个前缀的左部点数量减去右部点数量的最大值。如果最大值 \(\ge 0\),考虑找到第一个最大值的位置 \(p\),再找到 \(r_j\le p\) 的满足 \(l_j\) 最小(优先级最小)的区间 \(j\),然后将对应的匹配移到 \(\le i\) 的部分。删掉的匹配数为最大值减去 \([i + 1, l_j - 1]\) 的最大值,重复此流程即可。

分析复杂度。发现每次更新一次匹配,线段树上至少有一个节点的右儿子最大值从大于左儿子最大值变为不超过左儿子最大值,所以总时间复杂度为 \(\mathcal O(n\log^2 n)\)


  • 理清思路,不要被假做法害了。

  • 如果实在想不到就换个方向,换可小可大。


点击查看代码
#include <bits/stdc++.h>
#define ll int
#define LL long long
#define uLL unsigned LL
#define fi first
#define se second
#define mkp make_pair
#define pir pair<ll, ll>
#define pb push_back
#define i128 __int128
using namespace std;
char buf[1 << 22], *p1, *p2;
// #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, (1 << 22) - 10, stdin), p1 == p2)? EOF :
// *p1++)
template <class T>
const inline void rd(T &x) {char ch;bool neg = 0;while (!isdigit(ch = getchar()))if (ch == '-')neg = 1;x = ch - '0';while (isdigit(ch = getchar())) x = (x << 1) + (x << 3) + ch - '0';if (neg)x = -x;
}
const ll maxn = 1e5 + 10, M = 1e6 + 10, mod = 1e9 + 7;
const LL inf = 1e18;
ll power(ll a, ll b = mod - 2, ll p = mod) {ll s = 1;while (b) {if (b & 1)s = 1ll * s * a % p;a = 1ll * a * a % p, b >>= 1;}return s;
}
template <class T, class _T>
const inline ll pls(const T x, const _T y) { return x + y >= mod ? x + y - mod : x + y; }
template <class T, class _T>
const inline ll mus(const T x, const _T y) { return x < y ? x + mod - y : x - y; }
template <class T, class _T>
const inline void add(T &x, const _T y) { x = x + y >= mod ? x + y - mod : x + y; }
template <class T, class _T>
const inline void sub(T &x, const _T y) { x = x < y ? x + mod - y : x - y; }
template <class T, class _T>
const inline void chkmax(T &x, const _T y) { x = x < y ? y : x; }
template <class T, class _T>
const inline void chkmin(T &x, const _T y) { x = x < y ? x : y; }ll T, n, m, a[maxn], l[maxn], r[maxn], c[maxn], b[maxn];
LL sum;
vector <ll> vecl[maxn], vecr[maxn];struct SGT {LL tag[maxn << 2]; pair <LL, ll> mx[maxn << 2];void addtag(ll p, LL v) { mx[p].fi += v, tag[p] += v; }void pushdown(ll p) {addtag(p << 1, tag[p]), addtag(p << 1|1, tag[p]);tag[p] = 0;}void modify(ll p, ll l, ll r, ll x, ll v) {if(l >= x) return addtag(p, v);pushdown(p); ll mid = l + r >> 1;if(x <= mid) modify(p << 1, l, mid, x, v);modify(p << 1|1, mid + 1, r, x, v);mx[p] = max(mx[p << 1], mx[p << 1|1]);}void build(ll p, ll l, ll r) {mx[p] = mkp(0ll, -l), tag[p] = 0;if(l == r) return; ll mid = l + r >> 1;build(p << 1, l, mid), build(p << 1|1, mid + 1, r);}LL query(ll p, ll l, ll r, ll x) {if(r <= x) return mx[p].fi;if(x < l) return -inf;pushdown(p); ll mid = l + r >> 1;return max(query(p << 1, l, mid, x), query(p << 1|1, mid + 1, r, x));}
} tr1, tr2;set <pir> st[maxn];
struct _SGT {pir mn[maxn << 2];void modify(ll p, ll l, ll r, ll x, pir t, ll v) {if(l == r) {if(v == 1) st[l].insert(t);else st[l].erase(t);mn[p] = st[l].empty()? mkp(n + 1, 0) : *st[l].begin();return;} ll mid = l + r >> 1;if(x <= mid) modify(p << 1, l, mid, x, t, v);else modify(p << 1|1, mid + 1, r, x, t, v);mn[p] = min(mn[p << 1], mn[p << 1|1]);}pir query(ll p, ll l, ll r, ll x) {if(r <= x) return mn[p];ll mid = l + r >> 1;if(x <= mid) return query(p << 1, l, mid, x);return min(query(p << 1, l, mid, x), query(p << 1|1, mid + 1, r, x));}
} tr3;void solve() {rd(n), rd(m); sum = 0;tr1.build(1, 1, n), tr2.build(1, 1, n);for(ll i = 1; i <= n; i++) {rd(a[i]), vecl[i].clear(), vecr[i].clear();tr1.modify(1, 1, n, i, -a[i]);}for(ll i = 1; i <= m; i++) {rd(l[i]), rd(r[i]), rd(c[i]);vecl[l[i]].pb(i), vecr[r[i]].pb(i);}for(ll i = 1; i <= n; i++) st[i].clear();for(ll i = 1; i <= 4 * n; i++) tr3.mn[i] = mkp(n + 1, 0);for(ll i = 1; i <= n; i++) {for(ll j: vecr[i - 1]) {sum -= c[j];tr2.modify(1, 1, n, n - l[j] + 1, -c[j]);}tr1.modify(1, 1, n, i, a[i]);tr2.modify(1, 1, n, n - i + 1, -a[i]);for(ll j: vecl[i]) {sum += c[j], b[j] = c[j];tr1.modify(1, 1, n, r[j], c[j]);tr3.modify(1, 1, n, r[j], mkp(l[j], j), 1);}while(tr1.mx[1].fi > 0) {ll pos = -tr1.mx[1].se, id = tr3.query(1, 1, n, pos).se;LL tmp = max(0ll, tr1.query(1, 1, n, pos - 1));ll w = min((LL) b[id], tr1.mx[1].fi - tmp);b[id] -= w, tr1.modify(1, 1, n, r[id], -w);tr2.modify(1, 1, n, n - l[id] + 1, w);if(!b[id]) tr3.modify(1, 1, n, r[id], mkp(l[id], id), -1);}printf("%lld ", sum - max(0ll, tr2.mx[1].fi));} puts("");
}int main() {rd(T); while(T--) solve();return 0;
}
http://www.gsyq.cn/news/28624.html

相关文章:

  • LLM学习笔记DAY10
  • LLM学习笔记DAY9
  • 无需接入执行器,0 代码改造实现微服务任务调度
  • 2025 废气处理/废气治理/环保/污水/分子筛/除臭设备推荐榜:上海深城以专利技术破局,3 家企业凭场景适配登榜,助力异味治理升级
  • API 搜索的下一代形态-Apipost智能搜索:只需用业务语言描述需求,就能精准定位目标接口!
  • 2025拖鞋机/酒店拖鞋生产线厂家推荐昆仑智能,高效稳定自动化解决方案
  • [sed] replace the first line with certain info
  • 2025提升机/自动提升机厂家推荐垚林机械,高效稳定省心之选
  • 配置Modbus TCP转RS485模块读取温度内容
  • redis-配置优化
  • 2025发电机/发电机组/柴油发电机/甲醇发电机组租赁厂家推荐新疆泓浩机电,专业维修保养服务保障
  • leetcode_146 LRU缓存 - 详解
  • 2025 年压滤机厂家最新推荐排行榜:隔膜 / 污泥 / 真空 / 板框 / 带式压滤机优质品牌权威指南
  • 2025 年氮化硅陶瓷球生产厂家最新推荐榜:高精度高耐磨产品优选,国内优质企业全面剖析
  • 详细介绍:python(73) 引用.dll文件并调用函数
  • harbor基于自建证书部署HTTPS及k8s集群
  • Windows 命令行查看COM口
  • 【IEEE出版】第六届计算机通信与网络安全国际学术会议(CCNS 2025)
  • playwright自动化测试应用-Day1
  • 改进的(μ+λ)约束差分进化算法设计与实现
  • 2025耳机/DC/防水耳机插座厂家推荐皓富电子,专业品质保障
  • 2025年口碑好的载带成型机厂家最新权威推荐榜
  • Mac Jenkins 环境部署
  • 达梦数据库(DM)同机 异机备份到 MinIO(Java 实现 干货直给)
  • 氛围编程:IT领导者须知
  • Day22-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\File-FileTest1~4
  • 实用指南:计算机中用8位如何计算最大值和最小值-128~127
  • 权威调研榜单:徐州CCC产品认证公共服务平台TOP3榜单好评深度解析
  • 权威调研榜单:落地立式护眼灯厂家TOP3榜单好评深度解析
  • 详细介绍:C++面向对象编程——引用