2022-04-14每日刷题打卡

代码源——每日一题

上帝的集合 - 题目 - Daimayuan Online Judge

题目描述

现在上帝有一个空集合,现在他命令你为他执行下列三种操作 n 次,他每次会给你一个操作类型 op。

操作1:向集合中插入一个整数 x;

操作2:将集合中所有的数加上 x;

操作3:输出集合中最小的数,并从集合中将他删除,如果存在多个最小的整数,任意选择一个即可;

输入描述

第一行输入一个整数 n;

接下来的 n 行,每行的输入如下所示。第一个数代表 op,如果 op=1 或 op=2,第二个数代表 xi:

1 xi

2 xi

3

输出描述

如果 op=3,请输出集合中的最小值。

样例输入

7
1 2
1 1
3
1 3
2 5
3
3

样例输出

1
7
8

数据范围

2≤n≤10^6, 1≤xi≤10^12

第一个操作:向集合中插入值。这个操作并不难,有非常多的方法都能做到。

第三个操作:输出最小值并删除。我们利用优先队列或mulset等容器都可以很方便的做到。

问题就是第二个操作,怎么能在短时间内把所有的值都加上1?说到区间修改有的人可能会想到线段树,确实,线段树是个可行的方法,加上lz标记后,我们可以在logn的时间内做到区间修改,并且只要每个点存储的都是区间内的最小值,我们就可以在logn的时间内完成区间修改,logn的时间内找到最小值并将其删除,logn的时间内插入一个元素。

但是lz标记这种东西写起来我觉得太麻烦了!我们有没有办法能做到更简便的完成操作二?

当然是有的,我才不想跑去写lz标记。我们可以假装把所有的元素都加上x,我们用一个变量add存下所有加在全体的x,只要第三次操作输出值的时候把add加上那个值即可。那么有个问题,比如我前面先插入几个元素后全体加10,然后插入了一个很小的元素,这样操作三会输出这个很小的元素,输出的时候会加上add,但是这个元素在逻辑上并没有加上10,怎么办?好解决,我们只要插入的时候,把元素预先减去add再插入即可,比如我这里插入的11,但实际插入的是1。这样在再输出的也是11。至于操作一和三,我们只要找一个能很快找到最小值的容器就行。

1:优先队列(小根堆)

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 10;int main()
{ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);ll t,add=0;priority_queue<ll,vector<ll>,greater<ll>>que;cin >> t;while (t--){int st;cin >> st;if (st == 1){ll x;cin >> x;que.push(x-add);}else if (st == 2){ll x;cin >> x;add += x;}else{cout << que.top()+add << endl;que.pop();}}return 0;
}

2.线段树

这个有点特殊,因为线段树是很难直接加入一个新的点的,但我们可以提前开好空间,这里一共操作数是10^6,假设这全是插入操作,加上保险起见,我们最多开他一个4*1e6+40的线段树,一共有1e6+10个叶子,为了不影响结果,我们把所有的叶子都整成很大的值。然后照着这些位置一个个插入值即可,至于删除操作,我们直接把那个叶子的值改成很多的值即可。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 10;
ll f[4 * N],len=0;void inserttree(ll k, ll l, ll r, ll x,ll y)
{if (l == r){f[k] = y;return;}ll m = (l + r) / 2;if (x <= m)inserttree(k + k, l, m, x, y);else inserttree(k + k + 1, m + 1, r, x, y);f[k] = min(f[k + k], f[k + k + 1]);
}ll calc(ll k, ll l, ll r)
{if (l == r){ll ans = f[k];f[k] = 1e15;return ans;}ll m = (l + r) / 2,res;if (f[k + k]<= f[k + k + 1])res = calc(k + k, l, m);else res = calc(k + k + 1, m + 1, r);f[k] = min(f[k + k], f[k + k + 1]);return res;
}int main()
{ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);ll t,add=0;cin >> t;memset(f, 0x3f3f, sizeof f);int a = 0;while (t--){ll st, x;cin >> st;if (st == 1){cin >> x;len++;inserttree(1, 1, 1000000, len, x - add);}else if (st == 2){cin >> x;add += x;}else{cout << 1LL*(calc(1, 1, 1000000)+add) << endl;}}return 0;
}

CodeForces——线段树专题

B - Segment Tree, part 1 - Codeforces

This problem is the reversed version of the previous one. There was a permutation pi of n elements, for each ii we wrote down the number ai, the number of j such that j<i and pi<pj. Restore the original permutation for the given ai.

Input

The first line contains the number n (1≤n≤10^5), the second line contains n numbers ai. It is guaranteed that ai were obtained from some permutation using the procedure described in the statement.

Output

Print n numbers, the original permutation.

Example

input

5
0 1 1 0 3

output

4 1 3 5 2

这题是说,有这么一个数组a,他有个对应的数组b,b的每一位是a的对应位置上,它的左边有多少个大于他的个数,现在他给你了这个数组b,让你求出数组a。

用线段树来写就是,我们从右往左遍历数组b,准备一个线段树,初始叶子都是1。我们每次在线段树里找从右往左数,找第b[i]个1的位置。之后把那个位置的叶子变成0。

为什么这样可以得到结果?首先,我们是从右往左数第b[i]个1的个数,右边的点都是大于左边的点的。而且因为之前数过的叶子都会变成0,说明变成0的叶子在结果的a数组里应该出现在我们当前找的位置的右边,而我们找的是左边有多少个大于我们的个数。所以就要从右往左找第b[i]个叶子的位置。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>#define endl '\n';
typedef long long ll;
typedef pair<int, int> PII;
const int N = 100050;
int f[4 * N], a[N], n;void buildtree(int k, int l, int r)
{if (l == r){f[k] = 1;return;}int m = (l + r) / 2;buildtree(k + k, l, m);buildtree(k + k + 1, m + 1, r);f[k] = f[k + k] + f[k + k + 1];
}void revise(int k, int l, int r, int x)
{if (l == r){f[k] = 0;return;}int m = (l + r) / 2;if (x <= m)revise(k + k, l, m, x);elserevise(k + k + 1, m + 1, r, x);f[k] = f[k + k] + f[k + k + 1];
}int quire(int k, int l, int r, int x)
{if (l == r){return l;}int m = (l + r) / 2;if (f[k + k + 1] >= x)return quire(k + k + 1, m + 1, r, x);else return quire(k + k, l, m, x - f[k + k + 1]);
}int main()
{cin >> n;for (int i = n; i >= 1; i--){cin >> a[i];a[i]++;}buildtree(1, 1, n);vector<int>v(n);for (int i = 1; i <= n; i++){v[i - 1] = quire(1, 1, n, a[i]);revise(1, 1, n, v[i - 1]);}for (int i = n - 1; i >= 0; i--)cout << v[i] << " ";return 0;
}

2022-04-14每日刷题打卡相关推荐

  1. 2022.10.14每日刷题打卡

    リモコン 题意: 题目描述: 高桥君要调整空调的设定温度.现在的设定温度是A度,而他想调到B度. 空调遥控器按一次可以: 上调或下调1度 上调或下调5度 上调或下调10度 高桥君想求出从A调到B度的最 ...

  2. 2022.11.14每日刷题打卡

    过山车 原题链接:传送门 二分图最大匹配模板题,但sb了数组开小了一直TLE,虽然是模板但很长教训. #include <bits/stdc++.h> using namespace st ...

  3. 2022-03-02每日刷题打卡

    2022-03-02每日刷题打卡 代码源--div2每日一题 Alice的德州扑克 - 题目 - Daimayuan Online Judge 德州扑克是目前世界上最流行的扑克游戏,全世界有众多相关的 ...

  4. 2022-03-03每日刷题打卡

    2022-03-03每日刷题打卡 力扣--每日一题 258. 各位相加 给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数.返回这个结果. 示例 1: 输入: num = 38 输出 ...

  5. 2022-02-15每日刷题打卡

    2022-02-15每日刷题打卡 AcWing--算法基础 900. 整数划分 - AcWing题库 一个正整数 n 可以表示成若干个正整数之和,形如:n=n1+n2+-+nk,其中 n1≥n2≥-≥ ...

  6. 2022-04-01每日刷题打卡

    2022-04-01每日刷题打卡 代码源--每日一题 Lusir的游戏 - 题目 - Daimayuan Online Judge Lusir 正在玩一个古老的基于 DOS 的游戏. 游戏中有 N+1 ...

  7. 2021-12-11每日刷题打卡

    2021-12-11每日刷题打卡 力扣--剑指offer 剑指 Offer 40. 最小的k个数 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字, ...

  8. 2022-03-10每日刷题打卡

    2022-03-10每日刷题打卡 力扣--每日一题 589. N 叉树的前序遍历 给定一个 n 叉树的根节点 root ,返回 其节点值的 前序遍历 . n 叉树 在输入中按层序遍历进行序列化表示,每 ...

  9. 2022-03-31每日刷题打卡

    2022-03-31每日刷题打卡 代码源--每日一题 完美数 - 题目 - Daimayuan Online Judge 对于给定的数字 a , b ,当整数 n 在十进制下的所有数位都为 a 或 b ...

最新文章

  1. 用c++实现LR语法分析器 通过LR分析表及三个栈形成对输入表达式的判断!
  2. mysql makefile_编译安装mysql,找不到makefile
  3. [bzoj2527][Poi2011]Meteors_整体二分_树状数组
  4. 妈妈再也不担心我面试被 Redis 问得脸都绿了
  5. μC/OS-II软件定时器的分析与测试
  6. OpenCV里IplImage的widthStep参数 和width参数
  7. 商标45类分类表明细表_2019版注册商标分类表,商标注册45类范围明细
  8. Pytest全局用例共用之conftest.py详解
  9. C#解leetcode 53.Maximum Subarray
  10. excel保存时 检测到错误,Microsoft Excel可通过删除或修复某些功能来保存此文件
  11. 【spring】常用注解作用归纳
  12. 软件测试固态硬盘健康状态良好,别被忽悠!3分钟教你搞懂SSD性能测试各项数据!...
  13. 基于C++和QT实现的房贷计算器设计
  14. 《金牌网管师——助理级网吧网管》目录
  15. 数字新基建指南|数据智能如何赋能文旅新增长
  16. 低成本快速开发 LoRa 终端:从 0 到 1
  17. 深度学习各类优化器详解(动量、NAG、adam、Adagrad、adadelta、RMSprop、adaMax、Nadam、AMSGrad)
  18. IDMPhotoBrowser 图片管理器
  19. webflux 过滤器 WebFilter
  20. 进销存系统 通用进销存行业商用财务系统

热门文章

  1. 微信小程序实现五星评分效果
  2. 3分钟了解阿里云自营建站服务。
  3. 导出DNS服务器上的记录
  4. 《那些年啊,那些事——一个程序员的奋斗史》——100
  5. 【网络】为什么百度查到的ip和ipconfig查到的不一样;详解公网Ip和私网ip;详解网络分类ABC;
  6. 文献阅读(60)ACL2021-Attention Calibration for Transformer in Neural Machine Translation
  7. 曼哈顿算法公式_距离计算方法总结 | Public Library of Bioinformatics
  8. python提取excel指定关键词的行数据
  9. 今日锋评:愚人节的秘密
  10. 数画-AI绘画-免费的人工智能AI绘画网站