BUPT2017 springtraining(16) #2 ——基础数据结构
题目在这里
A.似乎是个并查集+???
B.10W的范围,似乎可以暴力来一发二分+sort?
但我猜正解可以O(nlogn)?
C.单调队列入门题目
- #include <cstdio>
- int n, m, a[], ans1[], ans2[];
- struct queue_1 {
- int q[];
- int l, r;
- queue_1(): l(), r() {}
- int front() {
- return q[l];
- }
- void push(int i) {
- while(l <= r && q[l] + m <= i) l ++;
- while(r >= l && a[i] <= a[q[r]]) r --;
- q[++ r] = i;
- }
- }q1;
- struct queue_2 {
- int q[];
- int l, r;
- queue_2(): l(), r() {}
- int front() {
- return q[l];
- }
- void push(int i) {
- while(l <= r && q[l] + m <= i) l ++;
- while(r >= l && a[i] >= a[q[r]]) r --;
- q[++ r] = i;
- }
- }q2;
- void getint(int &x) {
- x = ;
- static int c, f;
- while(c = getchar(), (c < '' || c > '') && c != '-');
- if(c != '-') x = c - '', f = ;
- else f = , x = ;
- while(c = getchar(), c >= ''&&c <= '') x = x * + c - '';
- if(f) x = -x;
- }
- int main() {
- getint(n), getint(m);
- for(int i = ;i < m;i ++) getint(a[i]), q1.push(i), q2.push(i);
- for(int i = m;i <= n;i ++)
- getint(a[i]), q1.push(i), q2.push(i),
- ans1[++ ans1[]] = a[q1.front()], ans2[++ ans2[]] = a[q2.front()];
- for(int i = ;i <= ans1[];i ++) printf("%d ", ans1[i]);puts("");
- for(int i = ;i <= ans2[];i ++) printf("%d ", ans2[i]);
- return ;
- }
我怎么就脑子抽了写了个极丑的封装呢
注意选择C++,G++会超时
D.简单的单点修改+区间查询max
线段树即可,据说这题还能有树状数组的骚操作?
比较懒,写了两个好写一点的
分块
- #include <cstdio>
- int n, m, siz;
- int a[], mmax[];
- int max(int x, int y){
- return x > y ? x : y;
- }
- int main() {
- int x, y, z;
- char str[];
- while(scanf("%d %d", &n, &m) != EOF) {
- for(siz = ;siz * siz < n;siz ++);
- for(int i = ;i <= n / siz;i ++) mmax[i] = ;
- for(int i = ;i < n;i ++)
- scanf("%d", &a[i]), mmax[i / siz] = max(mmax[i / siz], a[i]);
- while(m --) {
- scanf("%s %d %d", str, &x, &y);
- if(str[] == 'Q') {
- z = , x --, y --;
- if(x / siz == y / siz) {
- for(int i = x;i <= y;i ++)
- z = max(z, a[i]);
- }
- else {
- for(int i = x;i < x / siz * siz + siz;i ++)
- z = max(z, a[i]);
- for(int i = y / siz * siz;i <= y;i ++)
- z = max(z, a[i]);
- for(int i = x / siz + ;i < y / siz;i ++)
- z = max(z, mmax[i]);
- }
- printf("%d\n", z);
- }
- else {
- x --, a[x] = y, mmax[x / siz] = ;
- for(int i = x / siz * siz;i < x / siz * siz + siz;i ++)
- mmax[i / siz] = max(mmax[i / siz], a[i]);
- }
- }
- }
- }
zkw线段树
- #include <cstdio>
- int n, m, M;
- int tr[];
- int max(int x, int y){
- return x > y ? x : y;
- }
- int main() {
- int x, y, z;
- char str[];
- while(scanf("%d %d", &n, &m) != EOF) {
- for(M = ;M < n + ;M <<= );
- for(int i = M + ;i <= M + n;i ++) scanf("%d", &tr[i]);
- for(int i = M + n + ;i <= (M << );i ++) tr[i] = ;
- for(int i = M;i >= ;i --) tr[i] = max(tr[i << ], tr[i << | ]);
- while(m --) {
- scanf("%s %d %d", str, &x, &y);
- if(str[] == 'Q') {
- z = ;
- for(int s = x + M - , t = y + M + ;s ^ t ^ ;s >>= , t >>= ) {
- if(~s & ) z = max(z, tr[s ^ ]);
- if( t & ) z = max(z, tr[t ^ ]);
- }
- printf("%d\n", z);
- }
- else {
- for(tr[x += M] = y, x >>= ;x;x >>= )
- tr[x] = max(tr[x << ], tr[x << | ]);
- }
- }
- }
- }
多组数据的话,基本注意每次都clear一下就好了
另外分块更滋磁下标从0开始计算
但是如果题目明确标号从1-n就要另外注意一下了
E.一个简单的队列套队列,代码供参考
- #include <queue>
- #include <cstdio>
- #include <iostream>
- #define rep(i, j, k) for(int i = j;i <= k;i ++)
- using namespace std;
- queue <int> q, a[];
- int n, bel[];
- int main() {
- int m, x, t = ;
- char str[];
- ios::sync_with_stdio(false);
- while(cin >> n, n != ) {
- printf("Scenario #%d\n", ++ t);
- rep(i, , n) {
- cin >> m;
- rep(j, , m) cin >> x, bel[x] = i;
- }
- while(cin >> str, str[] != 'S') {
- if(str[] == 'E') {
- cin >> x;
- if(!a[bel[x]].size()) q.push(bel[x]);
- a[bel[x]].push(x);
- }
- else {
- printf("%d\n", a[q.front()].front());
- a[q.front()].pop();
- if(!a[q.front()].size()) q.pop();
- }
- }
- while(!q.empty()) q.pop();
- rep(i, , n) while(!a[i].empty()) a[i].pop();
- puts("");
- }
- }
F.无修改区间最值问题,直接上线段树(我写的zkw
- #include <cstdio>
- int n, m, M, tr[][];
- int min(int x, int y) {
- return x < y ? x : y;
- }
- int max(int x, int y) {
- return x > y ? x : y;
- }
- int main() {
- int s, t, r, l;
- scanf("%d %d", &n, &m);
- for(M = ;M < n + ; M <<= );
- for(int i = M + ;i <= M + n;i ++) scanf("%d", &tr[][i]), tr[][i] = tr[][i];
- for(int i = M + n + ;i <= M << ;i ++) tr[][i] = ;
- for(int i = M;i;i --)
- tr[][i] = max(tr[][i << ], tr[][i << | ]),
- tr[][i] = min(tr[][i << ], tr[][i << | ]);
- while(m --) {
- scanf("%d %d", &s, &t), r = , l = ;
- for(s += M - , t += M + ;s ^ t ^ ;s >>= , t >>= ) {
- if(~ s & ) r = max(r, tr[][s ^ ]), l = min(l, tr[][s ^ ]);
- if( t & ) r = max(r, tr[][t ^ ]), l = min(l, tr[][t ^ ]);
- }
- printf("%d\n", r - l);
- }
- return ;
- }
G.并查集+堆的启发式合并
总之手写堆大概只是用来理解其原理的
平时写题又不卡常数还是priority_queue大法好啊
顶多撸个简单的 '<' 重载美滋滋
- #include <queue>
- #include <cstdio>
- using std::queue;
- using std::priority_queue;
- priority_queue <int> q[];
- int n, m, f[], a[];
- void swap(int &x, int &y) {
- x ^= y, y ^= x, x ^= y;
- }
- int find_(int x) {
- if(f[x] != x) return f[x] = find_(f[x]);
- return x;
- }
- int main() {
- int x, y, z;
- while(scanf("%d", &n) != EOF) {
- for(int i = ;i <= n;i ++)
- f[i] = i, scanf("%d", &a[i]), q[i].push(a[i]);
- scanf("%d", &m);
- while(m -- ){
- scanf("%d %d", &x, &y);
- x = find_(x), y = find_(y);
- if(x == y) puts("-1");
- else {
- if(q[x].size() < q[y].size()) swap(x, y);
- z = q[x].top(), q[x].pop(), q[x].push(z >> );
- z = q[y].top(), q[y].pop(), q[y].push(z >> );
- f[y] = x;
- while(!q[y].empty()) q[x].push(q[y].top()), q[y].pop();
- printf("%d\n", q[x].top());
- }
- }
- for(int i = ;i <= n;i ++)
- while(!q[i].empty()) q[i].pop();
- }
- }
H.把如何锯木头看成如何拼木头
就是个石子合并问题,或者说哈夫曼树构造问题
- #include <iostream>
- #include <queue>
- #define rep(i, j, k) for(int i = j;i <= k;i ++)
- #define rev(i, j, k) for(int i = j;i >= k;i --)
- using namespace std;
- typedef long long ll;
- priority_queue <ll, vector<ll>, greater<ll> > q;
- ll ans, a, w;
- int n;
- int main() {
- ios::sync_with_stdio(false);
- cin >> n;
- rep(i, , n) cin >> a, q.push(a);
- rep(i, , n) w = q.top(), q.pop(), w += q.top(), q.pop(), ans += w, q.push(w);
- cout << ans;
- return ;
- }
I.很裸的并查集
我们用 i 和 i + n 来代表虫 i 的两个相反性别
而如果有 x 和 y 交配,那么显然有
x 和 y + n 为同一性别
y 和 x + n 为同一性别
即 union(x, y + n), union(y, x + n)
所以最终在同一集合中的小虫都必须是同一性别
而如果存在 i,满足 i 和 i + n 在同一个集合中
那么显然存在矛盾了
- #include <cstdio>
- int Case, n, m, f[];
- int find_(int x) {
- if(f[x] != x) return f[x] = find_(f[x]);
- return x;
- }
- void union_(int x, int y) {
- x = find_(x), y = find_(y);
- if(x != y) f[y] = x;
- }
- int main() {
- int x, y, ans = ;
- scanf("%d", &Case);
- for(int t = ;t <= Case;t ++) {
- ans = , printf("Scenario #%d:\n", t);
- scanf("%d %d", &n, &m);
- for(int i = ;i <= n;i ++) f[i] = i, f[i + n] = i + n;
- for(int i = ;i <= m;i ++) {
- scanf("%d %d", &x, &y);
- union_(x, y + n), union_(x + n, y);
- }
- for(int i = ;i <= n;i ++)
- if(find_(i) == find_(i + n)) {
- ans = ;
- break;
- }
- puts(ans ? "No suspicious bugs found!\n" : "Suspicious bugs found!\n");
- }
- return ;
- }
J.看图没看题,可能是个单调队列?
K.太长没看
L.对区间们排个序,然后就是个简单的线段树?
M.树状数组查个逆序对啥的
那个不断往后放的操作其实就那样吧
减一下加一下它对逆序对数造成的影响就行了
- #include <cstdio>
- int n, a[], c[];
- int lowbit(int x) {
- return x & (-x);
- }
- void add(int i) {
- while(i <= n) c[i] ++, i += lowbit(i);
- }
- int ask(int i) {
- int ret = ;
- while(i > ) ret += c[i], i -= lowbit(i);
- return ret;
- }
- long long sum, ans;
- int main() {
- while(scanf("%d", &n) != EOF) {
- sum = ;
- for(int i = ;i <= n;i ++) c[i] = ;
- for(int i = ;i <= n;i ++)
- scanf("%d", &a[i]), a[i] ++, add(a[i]), sum += i - ask(a[i]);
- ans = sum;
- for(int i = ;i < n;i ++) {
- sum += n - - ask(a[i] - ) * ;
- if(sum < ans) ans = sum;
- }
- printf("%lld\n", ans);
- }
- }
N.map随便做,读入有点恶心就是了
我用的getline,因为直接cin读入string类型会忽略换行和空格
而getline就能读入一行,读入的一行为空的话,会有s[0] = '\0'
也就是读进来一个空串而不会被直接忽略这个空行
- #include <map>
- #include <iostream>
- using namespace std;
- map <string, string> p;
- string s1, s2, s;
- int main() {
- int i;
- ios::sync_with_stdio(false);
- while(getline(cin, s), s[] != '\0') {
- i = , s1 = "", s2 = "";
- while(s[i] != ' ') s1 += s[i ++];i ++;
- while(s[i] != '\0') s2 += s[i ++];
- p[s2] = s1;
- }
- while(cin >> s) {
- if(p[s] != "") cout << p[s] << endl;
- else cout << "eh\n";
- }
- return ;
- }
O.很裸的主席树,离线做有点费脑子?
P.简单题目,自己手算循环节即可
- #include<iostream>
- using namespace std;
- int a[] = {, , , , , };
- int main() {
- int t;
- long long n;
- cin >> t;
- while(t--) cin >> n, cout << a[n % ] << endl;
- return ;
- }
=
题后话:
poj真的很老旧了啊
1.bits/stdc++.h 这个全能库不支持
2.ios::sync_with_stdio(false)
取消cin与stdio的同步都不支持
就是加了这句话依旧是cin的速度...
3.G++和C++两个选项很迷
编译标准和运行时间都会有差别...
一个编译过了另一个可能编译不过...
一个提交超时另一个可能就通过了...
BUPT2017 springtraining(16) #2 ——基础数据结构的更多相关文章
- BUPT2017 springtraining(16) #4 ——基础数论
题目在这里 A.手动打表找规律得组合数 n -= 2, m -= 2, ans = C(n, m) #include <bits/stdc++.h> using namespace std ...
- BUPT2017 springtraining(16) #1 题解
https://vjudge.net/contest/162590 A: 不难发现,当L=R时输出L,当L<R时输出2. B: 贪心得配对.1和n配 2和n-1配,对与对直接只要花1个代价就可以 ...
- BUPT2017 springtraining(16) #6 ——图论
题目链接 A.容易发现最后字符的对应都是一对一的 或者说我们没办法出现最后多对一或者一对多的情况 所以只要算出 ‘a’ - 'z' 每个字符最后对应的字符即可 #include <cstdio& ...
- BUPT2017 springtraining(16) #3 ——搜索与动态规划
题目在这里啊 A.最长上升子序列,范围很小所以写了简单的O(n^2)算法 #include <iostream> #define rep(i, j, k) for(int i = j;i ...
- BUPT2017 springtraining(16) #1 ——近期codeforces简单题目回顾
这里是contest 8道题全部来源于 cf 的两场contest (出题人可真懒啊 Codeforces Round #411 (Div. 2)的ABCDE Codeforces Round #40 ...
- 理解 OpenStack + Ceph (4):Ceph 的基础数据结构 [Pool, Image, Snapshot, Clone]
本系列文章会深入研究 Ceph 以及 Ceph 和 OpenStack 的集成: (1)安装和部署 (2)Ceph RBD 接口和工具 (3)Ceph 物理和逻辑结构 (4)Ceph 的基础数据结构 ...
- Numpy基础数据结构 python
Numpy基础数据结构 NumPy数组是一个多维数组对象,称为ndarray.其由两部分组成: 实际的数据 描述这些数据的元数据 1.一维数组 import numpy as np ar = np.a ...
- Flink内存管理源代码解读之基础数据结构
概述 在分布式实时计算领域,怎样让框架/引擎足够高效地在内存中存取.处理海量数据是一个非常棘手的问题.在应对这一问题上Flink无疑是做得非常杰出的,Flink的自主内存管理设计或许比它自身的知名度更 ...
- redis 基础数据结构实现
参考文献 redis数据结构分析 Skip List(跳跃表)原理详解 redis 源码分析之内存布局 Redis 基础数据结构与对象 Redis设计与实现-第7章-压缩列表 在redis中构建了自己 ...
随机推荐
- NOI.AC #31. MST
好像又是神仙dp....gan了一早上 首先这是个计数类问题,上DP, 对于一个最小生成树,按照kruskal是一个个联通块,枚举边小到大合成的 假如当前边是树边,那么转移应该还是枚举两个块然后合并 ...
- 【NYOJ42】一笔画问题
一笔画问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 Position:http://acm.nyist.net/JudgeOnline/problem.php?pid= ...
- 在IIS上搭建WebSocket服务器(二)
服务器端代码编写 1.新建一个ASP.net Web MVC5项目 2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: using System; using System.Col ...
- HDU4336:Card Collector
题意 有n张卡片,每一次 有pi的概率买到第i张卡.求买到所有卡的期望购买次数. n<=20 解析 Solution 1:大力状压(就是步数除以方案数) #include<iostream ...
- Balanced Lineup(线段树)
http://poj.org/problem?id=3264 题意:n个数,q个询问,输出[l,r]中最大值与最小值的差. #include <stdio.h> #include < ...
- 使用php实现二叉搜索树
看到一位大神写的js的搜索树,自己也按照模式写了一个php的二叉搜索树. <?phpclass node{ public $data; public $key; public $left=nul ...
- Unity 代码改宏定义
两个函数 PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup); //所有宏定义 ; 分割 PlayerSettings.SetS ...
- [Swift通天遁地]三、手势与图表-(3)通过捏合手势放大和缩小图像视图
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- hadoop一主一从部署(1)
一.安装前说明 主机IP:192.168.132.128 从机IP:192.168.132.129 1. 所有的安装包我放在了/root/这个目录下,你要根据自己情况去修改,这点必须注意 2. 采用的 ...
- Jsoup爬虫获取公司纳税识别号
天眼查 /** * 根据公司名称获取统一社会信用代码 * * @author xiaofei.xian 日期:2019年3月20日 上午11:12:41 */ public class GetTaxN ...