DAY5共2题:

  • 储物点的距离(前缀和)

  • 糖糖别胡说,我真的不是签到题目(multiset,思维)

作者:Eriktse

简介:19岁,211计算机在读,现役ACM银牌选手力争以通俗易懂的方式讲解算法!️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)

原文链接(阅读原文获得更好阅读体验):https://www.eriktse.com/algorithm/1096.html

储物点的距离

题目链接:https://ac.nowcoder.com/acm/problem/14683

预处理出各点搬运到点1和点n的代价前缀和,以及区间重量和。

假如我们要将区间[5, 7]的物品全部搬运到3,代价应该是区间[5, 7]的物品全部搬运到的1,然后减去多搬的代价:[5, 7]的重量和 * dist(1, 3)。

上面是x < l的情况,x > r的情况类似。

l <= x <= r只需将区间[l, r]分为两部分求和即可。

记得取模,距离要取模,前缀和也要取模。

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int maxn = 2e5 + 9, p = 1e9 + 7;
  5. //sum_l[i]表示区间[1, i]的物品都运到点1的代价之和
  6. //prefix_a[i]表示区间[1, i]的物品重量之和
  7. //pos[i]是第i个点的位置,通过a[]作前缀和得到
  8. int a[maxn], pos[maxn], sum_l[maxn], sum_r[maxn], prefix_a[maxn];
  9. int n, m;
  10. //取模函数
  11. int mo(int x){return (x % p + p) % p;}
  12. int f(int x, int l, int r)
  13. {
  14. if(l > r)return 0;
  15. int res = 0;
  16. if(x <= l)
  17. {
  18. res = mo(sum_l[r] - sum_l[l - 1]);
  19. res = mo(res - mo(pos[x] - pos[1]) * mo(prefix_a[r] - prefix_a[l - 1]) % p);
  20. }
  21. else if(x >= r)
  22. {
  23. res = mo(sum_r[r] - sum_r[l - 1]);
  24. res = mo(res - mo(pos[n] - pos[x]) * mo(prefix_a[r] - prefix_a[l - 1]) % p);
  25. }
  26. return res;
  27. }
  28. signed main()
  29. {
  30. scanf("%lld %lld",&n, &m);
  31. pos[1] = 1;
  32. for(int i = 2, d;i <= n; ++ i)scanf("%lld", &d), pos[i] = pos[i - 1] + d;
  33. for(int i = 1;i <= n; ++ i)scanf("%lld", a + i);
  34. for(int i = 1;i <= n; ++ i)
  35. {
  36. sum_l[i] = mo(sum_l[i - 1] + a[i] * mo(pos[i] - pos[1]) % p);
  37. sum_r[i] = mo(sum_r[i - 1] + a[i] * mo(pos[n] - pos[i]) % p);
  38. }
  39. for(int i = 1;i <= n; ++ i)prefix_a[i] = mo(prefix_a[i - 1] + a[i]);
  40. while(m --)
  41. {
  42. int x, l, r;scanf("%lld %lld %lld", &x, &l, &r);
  43. int ans = 0;
  44. if(l <= x and x <= r)ans = mo(f(x, l, x - 1) + f(x, x + 1, r));
  45. else ans = f(x, l, r);
  46. printf("%lld\n", ans);
  47. }
  48. return 0;
  49. }

糖糖别胡说,我真的不是签到题目

题目链接:https://ac.nowcoder.com/acm/problem/14583

本题有两种解法,第一种容易理解,第二种效率更优。

第一种解法:正向,multiset。

发功次数可以用一个桶来记录,让[1, i]的所有点的属性值都+1,相当于把后面的都-1,用一个fix表示偏移量。

建立两个multiset表示两组中的糖糖,好处是可以快速找出能力值最小的,从而去除掉。

扫一遍,把第i只糖糖加入到属于它的集合中,然后将另外一个集合中已有的能力值小的糖糖进行删除,再检查此时是否有发功。

最后集合中留下的糖糖个数即为答案。

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int maxn = 1e6 + 9, inf = 8e18;
  5. struct Node
  6. {
  7. int a, b;
  8. }p[maxn];
  9. int add[maxn];
  10. void solve()
  11. {
  12. int n, m;scanf("%lld %lld",&n, &m);
  13. memset(add, 0, sizeof(int) * (n + 2));
  14. for(int i = 1;i <= n; ++ i)
  15. scanf("%lld %lld", &p[i].a, &p[i].b);
  16. //注意同一时间可能施法多次
  17. for(int i = 1, x;i <= m; ++ i)scanf("%lld", &x), add[x] ++;
  18. int fix = 0, cnt = 0;
  19. multiset<int> st[2];
  20. for(int i = 1;i <= n; ++ i)
  21. {
  22. int a = p[i].a, b = p[i].b - fix;
  23. st[a].insert(b);
  24. while(!st[a ^ 1].empty() and *st[a ^ 1].begin() < b)
  25. st[a ^ 1].erase(st[a ^ 1].begin()), cnt ++;
  26. fix += add[i];
  27. }
  28. printf("%lld\n", n - cnt);
  29. }
  30. signed main()
  31. {
  32. int _;scanf("%lld", &_);
  33. while(_ --)solve();
  34. return 0;
  35. }

第二种解法:反向,思维。

我们想这么一个问题,一个糖糖x是否会被删除取决于x出现之后,在另外一个集合中,是否出现了能力值高于x的能力值的糖糖y

那么我们逆向遍历,维护两个集合的最值,当前的新加入的糖糖x的能力值如果低于另外一个集合中已经存在的(即右边的)糖糖能力值的最大值,说明他后面会被某个糖糖y删除掉,直接打上标记,但是我们不用真的删除。

糖糖x还可以用于删除左边的另一个集合的能力值较小的糖糖。注意此时的发功应该在循环开始时进行修改。

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int maxn = 1e6 + 9, inf = 8e18;
  5. struct Node
  6. {
  7. int a, b;
  8. }p[maxn];
  9. int add[maxn];
  10. void solve()
  11. {
  12. int n, m;scanf("%lld %lld",&n, &m);
  13. memset(add, 0, sizeof(int) * (n + 2));
  14. for(int i = 1;i <= n; ++ i)
  15. scanf("%lld %lld", &p[i].a, &p[i].b);
  16. //注意同一时间可能施法多次
  17. for(int i = 1, x;i <= m; ++ i)scanf("%lld", &x), add[x] ++;
  18. int fix = 0, cnt = 0;
  19. int mx[2] = {-inf, -inf};
  20. for(int i = n;i >= 1; -- i)
  21. {
  22. fix += add[i];
  23. int a = p[i].a, b = p[i].b + fix;
  24. mx[a] = max(mx[a], b);
  25. if(mx[a ^ 1] > b)cnt ++;
  26. }
  27. printf("%lld\n", n - cnt);
  28. }
  29. signed main()
  30. {
  31. int _;scanf("%lld", &_);
  32. while(_ --)solve();
  33. return 0;
  34. }

本文由eriktse原创,创作不易,如果对您有帮助,欢迎小伙伴们点赞、收藏、留言

【ACM算法竞赛日常训练】DAY5题解与分析【储物点的距离】【糖糖别胡说,我真的不是签到题目】| 前缀和 | 思维的更多相关文章

  1. 【经验总结】Java在ACM算法竞赛编程中易错点

    一.Java之ACM易错点 1. 类名称必须采用public class Main方式命名 2. 在有些OJ系统上,即便是输出的末尾多了一个“ ”,程序可能会输出错误,所以在我看来好多OJ系统做的是非 ...

  2. ACM算法竞赛:抄课文

    题目如下: 比如现在要写一句话 Hello world 输入: n (n > 0) 比如输入的n为10,就将Hello world打印十 #include <stdio.h> #in ...

  3. (Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

    http://www.cnblogs.com/sxiszero/p/3618737.html 下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年 ...

  4. 算法竞赛入门经典+挑战编程+USACO

    下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinej ...

  5. 华南师大 2017 年 ACM 程序设计竞赛新生初赛题解

    题解 被你们虐了千百遍的题目和 OJ 也很累的,也想要休息,所以你们别想了,行行好放过它们,我们来看题解吧... A. 诡异的计数法 Description cgy 太喜欢质数了以至于他计数也需要用质 ...

  6. 算法竞赛入门经典训练指南——UVA 11300 preading the Wealth

    A Communist regime is trying to redistribute wealth in a village. They have have decided to sit ever ...

  7. <算法竞赛入门经典> 第8章 贪心+递归+分治总结

    虽然都是算法基础,不过做了之后还是感觉有长进的,前期基础不打好后面学得很艰难的,现在才慢慢明白这个道理. 闲话少说,上VOJ上的专题训练吧:http://acm.hust.edu.cn/vjudge/ ...

  8. 2015浙江财经大学ACM有奖周赛(一) 题解报告

    2015浙江财经大学ACM有奖周赛(一) 题解报告 命题:丽丽&&黑鸡 这是命题者原话. 题目涉及的知识面比较广泛,有深度优先搜索.广度优先搜索.数学题.几何题.贪心算法.枚举.二进制 ...

  9. Aho-Corasick automaton(AC自动机)解析及其在算法竞赛中的典型应用举例

    摘要: 本文主要讲述了AC自动机的基本思想和实现原理,如何构造AC自动机,着重讲解AC自动机在算法竞赛中的一些典型应用. 什么是AC自动机? 如何构造一个AC自动机? AC自动机在算法竞赛中的典型应用 ...

  10. 算法竞赛入门经典 LA 4329(树状数组)

    题意: 一排有着不同能力值的人比赛,规定裁判的序号只能在两人之间,而且技能值也只能在两人之间 问题: <算法竞赛入门经典-训练指南>的分析: 上代码: #include<iostre ...

随机推荐

  1. sql文件导入错误,There was an error while executing a query. The query and the error message has been logged at: C:\U

    x.sql转储文件导入异常. 之前成功导入过,再次导入异常. 1修改my.ini文件,2修改sql文件编码.都不适用. 解决方法:新建数据库,再次导入成功.注意编码.

  2. Spring系列之资源-11

    目录 `Resource` 内置`Resource`实现 `UrlResource` `ClassPathResource` `FileSystemResource` `ServletContextR ...

  3. 网页元素间距测量(better rule插件的使用)

    我们在测试UI界面的时候,需要测量各元素大小及元素之间的距离.元素大小,使用F12可以简易的得到数据,但是元素的间距相对来说会比较复杂.这里推荐一款chrome插件better rule,帮助大家测量 ...

  4. poi解析Excel2007海量数据

    处理excel,开源的javaApI提供了两种,一种是jxl,一种是poi.poi提供的功能较多,所以我用的是poi. poi有两种模式,一个是用户模式(HSSFworkbook:支持Excel200 ...

  5. 工作随笔1-从slave备份,恢复成新得从库

    innobackupex --slave-info --safe-slave-backup --no-timestamp tmp_lastinnobackupex --apply-log tmp_la ...

  6. 2003031120—廖威—Python数据分析第七周作业—MySQL的安装以及使用

    项目    内容 课程班级博客链接 https://edu.cnblogs.com/campus/pexy/20sj 这个作业要求链接  https://edu.cnblogs.com/campus/ ...

  7. CountDownLatch/CyclicBarrierDemo/Samaphore

    CountDownLatch CountDownLatch:让一些线程阻塞直到另外一些完成后才被唤醒 CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞 ...

  8. P3512 [POI2010]PIL-Pilots 单调队列的应用

    题目描述 给定n,k和一个长度为n的序列,求最长的最大值最小值相差不超过k的序列 输入格式 第一行两个有空格隔开的整数k(0<=k<=2000,000,000),n(1<=n< ...

  9. CF1338E JYPnation

    题意:给定一个竞赛图,且其中不包含任意一组三元环 $(a, b, c)$,满足 $a \to d$,$b \to d$,$c \to d$,求每个点两两之间的距离之和(若无法达到即为 $614n$). ...

  10. WPF dxe:ComboBoxEdit 选择项后并可编辑值

    有个需要,在ComboBoxEdit中选择多个值,并且要求可以直接在后面添加新的值. 开始的时候绑定列表,设置DisplayMember,不能修改. 然后绑定List<string>,不设 ...