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

今日训练 ——线段树与二分法

两道算法题带你温故知新

  • NOIP2015 推销员
  • NOIP2011 质监员

今天两道noip的算法题练练手

NOIP2015 推销员

题目

可能会有更简单的写法,但利用线段树是最好想的方法。

  1. 贪心选择逻辑
    由于 s 数组递增,当前已访问的最大位置为 pos(即最远客户位置),后续选择只有两种最优可能:
    选 pos 左边的客户(s [i]<s [pos]):最大位置不变,总收益仅增加 a [i],新增收益为 a [i]。
    选 pos 右边的客户(s [i]>s [pos]):最大位置更新为 s [i],总收益增加 a [i] 且路程变为 2×s [i],新增总收益为 a [i]+2×s [i]。
    因此每次只需二选一:
    左边未访问客户中 a [i] 最大的(对应第一种选择)。
    右边未访问客户中(a [i]+2×s [i] - 2×s原)最大的(对应第二种选择)。

  2. 线段树的作用
    需要高效查询区间最值和位置,同时支持标记客户为 “已访问”(即排除该客户),因此用两棵线段树分别维护:
    线段树 1(maxv1):维护区间内 a [i] 的最大值及对应位置(查询左边客户)。
    线段树 2(maxv2):维护区间内(a [i]+2×s [i])的最大值及对应 s [i]、位置(查询右边客户)。

  3. 线段树核心操作
    (1)更新节点(up)
    线段树 1:比较左右子树的 a [i],取较大值对应的节点。
    线段树 2:比较左右子树的(a [i]+2s [i]),取较大值对应的节点。
    (2)建树(build)
    叶子节点:直接赋值(node1 存 a [i] 和位置,node2 存 a [i]、s [i] 和位置)。
    非叶子节点:递归建树后,通过 up 函数合并左右子树信息。
    (3)更新标记(update)
    将已访问的客户价值设为 0,使其不再被选中(线段树查询时会忽略 0 值)。
    (4)区间查询(query1/query2)
    query1:查询区间内 a [i] 的最大值及位置(左边客户查询)。
    query2:查询区间内(a [i]+2s [i])的最大值及对应信息(右边客户查询)。

  4. 主函数逻辑
    输入 s 数组(递增)和 a 数组,建树。
    初始化第一次选择:找出所有客户中(a [i]+2s [i])最大的客户(第一次访问的最优解),输出结果并标记为已访问。
    迭代 n-1 次(剩余 n-1 个客户):
    查询左边(1~pos-1)的最优客户(query1)。
    查询右边(pos+1~n)的最优客户(query2)。
    比较两种选择的收益,选更大的那个,更新总价值、最远位置,标记已访问并输出结果。

  5. 复杂度分析
    建树时间:O (nlogn)(两棵线段树均为 O (nlogn))。
    每次查询和更新:O (logn)(线段树单次操作复杂度)。
    总复杂度:O (nlogn),适配 n=1e5 的题目数据规模。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1;
int a[N], s[N];
struct node1 {node1() : sum (0), pos(0){};int sum;int pos;
}maxv1[N << 2];
struct node2 {node2() : sum (0), maxs(0), pos(0){};int sum;int maxs;int pos;
}maxv2[N << 2];
void up(int rt) {maxv1[rt]= maxv1[rt << 1].sum > maxv1[rt<< 1|1].sum ? maxv1[rt<<1] : maxv1[rt << 1 | 1];maxv2[rt]= maxv2[rt << 1].sum + maxv2[rt << 1].maxs * 2 > maxv2[rt << 1 | 1].sum + maxv2[rt << 1 | 1].maxs * 2 ? maxv2[rt << 1] : maxv2[rt <<1 |1];
}
void build(int l, int r, int rt) {if (l == r) {maxv1[rt].sum = a[l], maxv1[rt].pos = l;maxv2[rt].sum = a[l], maxv2[rt].pos = l ,maxv2[rt].maxs = s[l];return;}// int mid = l + (r - l) / 2;int mid = (l + r) >> 1;build(l, mid, rt << 1);build(mid + 1, r, rt << 1 | 1);up(rt);
}
void update(int l, int r, int p, int val, int rt) {if (l == r) {maxv1[rt].sum = val,maxv1[rt].pos = 0;maxv2[rt].sum = val,maxv2[rt].pos = 0,maxv2[rt].maxs = 0;return;}int mid = (l + r) >> 1;if (p <= mid) {update(l, mid, p, val, rt << 1);}else {update(mid + 1, r, p, val, rt << 1 | 1);}up(rt);
}
node1 query1(int jobl, int jobr, int l, int r, int rt) {if (jobl <= l && r <= jobr) {return maxv1[rt];}node1 ans;int mid = (l + r) >> 1;if (jobl <= mid) {node1 t = query1(jobl, jobr, l, mid, rt << 1);ans = ans.sum > t.sum ? ans : t;}if (jobr > mid) {node1 t = query1(jobl, jobr, mid + 1, r, rt << 1| 1);ans = ans.sum > t.sum ? ans : t;}return ans;
}
node2 query2(int jobl, int jobr, int l, int r, int rt) {if(jobl <= l && r <= jobr) return maxv2[rt];int mid = (l + r) >> 1;node2 ans;if(jobl <= mid) {node2 t = query2(jobl, jobr, l, mid, rt << 1);ans = ans.sum + ans.maxs * 2 > t.sum + t.maxs * 2 ? ans : t;}if(jobr > mid) {node2 t = query2(jobl, jobr, mid + 1, r, rt << 1 | 1);ans = (ans.sum + ans.maxs * 2 > t.sum + t.maxs * 2 ? ans : t);}return ans;
}
int main() {ios_base::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL);int n;cin>>n;for (int i = 1; i <= n; i++) {cin >> s[i];}for (int i = 1; i <= n; i++) {cin >> a[i];}build(1, n, 1);int sum = 0, maxs = 0, pos = 0;for (int i = 1; i <= n; i++) {if(s[i] * 2 + a[i] > sum + maxs * 2) sum = a[i], maxs = s[i], pos = i;}cout << sum + maxs * 2 << '\n';update(1, n, pos, 0, 1);for (int k = 1; k < n; k++) {node1 t1;node2 t2;if(pos - 1 > 0){t1 = query1(1, pos - 1, 1, n, 1);}// no posif(pos + 1 <= n) {t2 = query2(pos + 1, n, 1, n, 1);}int newpos;if (t2.sum + t2.maxs * 2 > t1.sum + maxs * 2) {sum += t2.sum;pos = t2.pos;newpos = t2.pos;cout << sum + t2.maxs * 2 << '\n';maxs = t2.maxs;}else {sum += t1.sum;newpos = t1.pos;cout << sum + maxs * 2 << '\n';}update(1, n, newpos, 0, 1);}return 0;
}

NOIP2011 质监员

题目

核心思路分析

  1. 二分查找的合理性
    W的取值直接影响Y的大小:
    当W增大时,重量≥W的矿石减少,cnt和sumv均可能减小,因此Y单调递减(非递增)。
    由于Y随W单调变化,可通过二分W的可能取值,高效逼近最优解。
  2. 前缀和优化区间计算
    对于每个候选W,需计算m个区间的cnt和sumv:
    若直接遍历每个区间统计,时间复杂度为O(n*m),会超时。
    改用前缀和数组:
    num[i]:前i个矿石中重量≥W的数量
    yy[i]:前i个矿石中重量≥W的价值总和
    对于区间[l, r],cnt = num[r] - num[l-1],sumv = yy[r] - yy[l-1],计算时间降至O(1)。
  3. 二分次数:W最大范围为1~1e18,二分次数约log2(1e18) ≈ 60次。
    单次 check 复杂度:O(n + m)(计算前缀和O(n),处理m个区间O(m))。
    总复杂度:O(60*(n + m)),对于n, m ≤ 2e5,总操作约2.4e7,完全满足时间要求。
#include<bits/stdc++.h>
#define int long long
const int N = 2e5+5;
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi;
struct p {int w;int v;
} a[N];
int n, m, s;
vector<pii> ran;
int ans = 0x3f3f3f3f3f3f3f3f;
bool check(int mid) {vi num(N, 0);vi yy(N, 0);int y = 0;for (int i = 1; i <= n; ++i) {if (a[i].w >= mid) {num[i] = num[i-1] + 1;yy[i] = yy[i-1] + a[i].v;} else {num[i] = num[i-1];yy[i] = yy[i-1];}}for (auto &tmp : ran) {int rr = tmp.second;int ll = tmp.first;int c = num[rr] - num[ll-1];int v_sum = yy[rr] - yy[ll-1];y += c * v_sum;}ans = min(ans, abs(s - y));return y > s;
}
signed main() {ios ::sync_with_stdio(false),cin.tie(0),cout.tie(0);cin >> n >> m>>s;ran.resize(m);for (int i = 1; i <= n; ++i) {cin >> a[i].w >> a[i].v;}for (int i = 0; i < m; i++) {cin >> ran[i].first >> ran[i].second;}int left = 1, right = 1e18;while (left < right) {int mid = left + (right - left) / 2;if (check(mid)) {left = mid + 1;} else {right = mid;}}cout << ans << '\n';return 0;
}

noip的题一年比一年难,对编程能力的考查越来越深刻。
明后天估计会更新计算几何或者icpc题解,感谢观看。

http://www.dtcms.com/a/488049.html

相关文章:

  • PyQt5事件机制
  • 建盏十大高端客户合肥搜索优化排名
  • DeviceNet 转 CC-Link IE 实现欧姆龙 NJ 与西门子 S7-1500 在汽车焊接质量监控系统的集成应用
  • 建立网站的正确方法网站导航排版布局
  • 免费论坛网站大全广州哪个区封了
  • 【JSP程序设计】作用域通信对象 — pageContext对象
  • wordpress视频 小程序志鸿优化设计电子版
  • 专做运动品牌的网站佛山顺德做网站
  • 黔西南州做网站js网站开发视频
  • 数据结构——字典树Trie(介绍、Java实现)
  • 有什么有趣的网站做网站第一步做什么
  • 知名网站制作公司管理会计
  • ceph 手动编辑 crush 规则
  • 湘潭网站建设湘潭营销型网站建设实训报告
  • 网站的风格有哪些创建一个平台多少钱
  • PG Scrub 全流程核心步骤清单
  • 优先级队列的学习
  • 如今做那些网站致富苏州手机社区网站建设
  • 广州青菜篮农业有限公司网站建设项目东莞公司做网站
  • 如何登录网站服务器昆明营销网站建设
  • 东莞市企业网站建设哪家好什么网站可以做推广的
  • 3DMAX神经网络拓扑结构图插件NeuralNetworkTopology使用方法详解
  • 运 算 符
  • 项目商业网站建设方案长春市网站优化公司
  • Oracle下载JDK无需登录
  • 模拟算法专题总结:直接按题意实现的艺术
  • 昭阳区住房和城乡建设管理局网站网站建设最低价
  • 济南市住房和城乡建设局网站wordpress多图主题
  • TOP TOY闯关港股上市:三大关键挑战亟待破局,品牌如何独立增长?
  • TDengine 数学函数 FLOOR 用户手册