最近在复习数据结构,发现套题不错,题目质量好,覆盖广,Data Structures部分包括Example,以及简单,中等,难三个部分,这几天把Example的做完了,

摘要如下:

通过这几题让我复习和练习了优先队列,并查集,并查集的路径压缩。

总结如下:

11995 - I Can Guess the Data Structure!

给出push,pop操作对应的序列,判定是stack, queue还是deque。

用上面三个数据结构对应模拟下push,pop的操作,将结果与输出进行比对,需要注意的是如果pop一个空的数据结构时,以上三者就都不是了。

#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
using namespace std; int main() { // freopen("ismall.in", "r", stdin);
// freopen("mysmall.ans", "w", stdout); int n;
while (scanf("%d", &n) != EOF) {
stack<int> s;
queue<int> q;
priority_queue<int> pq; bool is_stack = true;
bool is_queue = true;
bool is_priority_queue = true; for (int i = ; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
if (a == ) {
s.push(b);
q.push(b);
pq.push(b);
} else {
if (s.empty()) {
is_stack = is_queue = is_priority_queue = false;
continue;
} if (s.top() != b) {
is_stack = false;
}
if (q.front() != b) {
is_queue = false;
}
if (pq.top() != b) {
is_priority_queue = false;
} s.pop();
q.pop();
pq.pop();
}
} if (!is_stack && !is_queue && !is_priority_queue) {
printf("impossible\n");
} else if (is_stack && !is_queue && !is_priority_queue) {
printf("stack\n");
} else if (!is_stack && is_queue && !is_priority_queue) {
printf("queue\n");
} else if (!is_stack && !is_queue && is_priority_queue) {
printf("priority queue\n");
} else {
printf("not sure\n");
}
}
}

11991 - Easy Problem from Rujia Liu?

给定一个序列,有m次查询,每次查询给定一个数n,以及次数k,问说这个序列中n出现k次的索引。

每个数对应一个链表,从左往右,遇到每个数,对应将这个数的位置放进该数对应的链表中。

PS:把这题加强下,如果查询在一个区间内的某数n出现k次的位置的话,应该怎么做呢。

#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std; int main()
{
freopen("esmall.in", "r", stdin);
freopen("mye", "w", stdout); int n, m; while (scanf("%d%d", &n, &m) != EOF) {
vector<vector<int> > vv;
vv.resize();
for (int i = ; i < n; i++) {
int t;
scanf("%d", &t);
vv[t].push_back(i + );
} while (m--) {
int k, v;
scanf("%d%d", &k, &v);
if (k <= vv[v].size()) {
printf("%d\n", vv[v][k - ]);
} else {
printf("0\n");
}
}
}

1203 - Argus

有k个有序的序列(a, 2a, 3a, ..., ka), (b, 2b, 3b, ..., kb), ..., (x, 2x, 3x, ..., kx),这k^2个数中找出前k大的数。

将k个指针指向k个序列中尚未进入队列的最小的位置,每次从这些指针所指数中挑选出最小的数放进队列,然后将对应指针向后移动,当队列中达到k个时结束。从指针所指数中挑出最小数可以使用优先队列来操作,最后的复杂度是k*log(k)。

#include <iostream>
#include <queue>
#include <stdio.h>
using namespace std; class Query {
public:
Query() {}
Query(int q_num, int period) : seed_(), q_num_(q_num), period_(period) {}
int get_q_num() const { return q_num_; }
int get_query_value() const { return seed_ * period_; }
void increase() { seed_++; }
bool operator < (const Query &q) const {
if (this->get_query_value() != q.get_query_value()) {
return this->get_query_value() > q.get_query_value();
} else {
return this->get_q_num() > q.get_q_num();
}
}
private:
int q_num_, period_, seed_;
}; int main() {
char ch[];
priority_queue<Query> Q;
while (scanf("%s", ch)) {
if (ch[] == '#') {
break;
}
int q_num, period;
scanf("%d%d", &q_num, &period);
Q.push(Query(q_num, period));
} int K;
scanf("%d", &K);
while (K--) {
Query top = Q.top();
Q.pop(); printf("%d\n", top.get_q_num()); top.increase();
Q.push(top);
}
}

11997 - K Smallest Sums

有k个序列,从k个序列中各挑出一个数,求和得到sum,问说k^k种可能的sum中的前k小的sum是多少。

先将这k个序列排序,采用上题的算法思路,指针从位置i移到位置i+1,sum添加了num[i+1]-num[i],使用长度为k的pos{}数组记录k个序列的指针位置,将pos{}看做是图中一个节点的状态,从该状态最多可以扩展出k个状态,分别是k个位置的指针向后移动。扩展出的状态全部放入优先队列,最多扩展k次,每次最多扩展k个,因此最多有k^2个状态进队列,并做判重,最后挑出前k个值,有点类似Dijkstra算法。然而由于节点保存了pos{},因此节点对拷的时候,复杂度是O(k)的,所以复杂度是O(k^3*log(k)),还是TLE了。

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stdio.h>
using namespace std; const int MAXK = ; int arr[MAXK][MAXK]; class Node {
public:
Node() {}
Node(int k) : k_(k) {
sum_ = ;
for (int i = ; i < k_; i++) {
idx_[i] = ;
sum_ += arr[i][];
}
} int get_idx(int i) const { return idx_[i]; }
int get_sum() const { return sum_; } bool move(int i) {
if (idx_[i] < k_) {
idx_[i]++;
sum_ += (arr[i][idx_[i]] - arr[i][idx_[i] - ]);
return true;
} else {
return false;
}
} bool operator < (const Node& node) const {
if (sum_ != node.get_sum()) {
return sum_ > node.get_sum();
} else {
for (int i = ; i < k_; i++) {
if (idx_[i] != node.get_idx(i)) {
return idx_[i] < node.get_idx(i);
}
}
return false;
}
} private:
int k_, sum_, idx_[MAXK];
}; int main() { //freopen("ksmall.in", "r", stdin);
// freopen("k.in", "r", stdin);
// freopen("my_k", "w", stdout); int k, c = ;
while (scanf("%d", &k) != EOF) {
c++; priority_queue<Node> Q;
set<Node> passed; for (int i = ; i < k; i++) {
for (int j = ; j < k; j++) {
scanf("%d", &arr[i][j]);
}
sort(arr[i], arr[i] + k);
} Node init_node = Node(k);
Q.push(init_node);
passed.insert(init_node); for (int i = ; i < k; i++) {
Node top = Q.top();
Q.pop(); printf("%d ", top.get_sum()); for (int j = ; j < k; j++) {
Node next_node = top;
if (next_node.move(j)) {
if (passed.find(next_node) == passed.end()) {
passed.insert(next_node);
Q.push(next_node);
}
}
}
} printf("\n");
}
}

能AC的一种做法是,将问题简化,首先看两个序列的情况a[0], a[1], ..., a[k], b[0], b[1], ..., b[k],两两求和的所有k^2的情况可以摆成k个长度为k的有序序列,a[i]+b[0], a[i]+b[1], ..., a[i]+b[k], (1 <= i <= k),然后该问题转换为上题的原型。到此,两条序列转变成了一条序列,该序列是这两条序列中和的前k小,用这条序列再和第三条序列做同样的操作,接下来同理,进行(k-1)次该操作后,就可以求出sum的前k小了,复杂度是O(k^2*log(k))。

#include <iostream>
#include <algorithm>
#include <queue>
#include <stdio.h>
using namespace std; const int MAXK = ; int arr[MAXK][MAXK]; struct Node {
int idx, sum;
bool operator < (const Node& node) const {
return sum > node.sum;
}
}; int main() {
//freopen("k.in", "r", stdin);
//freopen("ksmall.in", "r", stdin);
//freopen("k.out", "w", stdout); int k;
int c = ;
while (scanf("%d", &k) != EOF) {
c++;
for (int i = ; i < k; i++) {
for (int j = ; j < k; j++) {
scanf("%d", &arr[i][j]);
}
sort(arr[i], arr[i] + k);
} for (int i = ; i < k; i++) {
// arr[0][...], arr[i][...]
priority_queue<Node> Q; for (int j = ; j < k; j++) {
Node node;
node.idx = ;
node.sum = arr[][j] + arr[i][];
Q.push(node);
} for (int j = ; j < k; j++) {
Node top = Q.top();
Q.pop(); arr[][j] = top.sum; if (top.idx < k - ) {
top.sum = top.sum - arr[i][top.idx] + arr[i][top.idx + ];
top.idx++; Q.push(top);
}
}
} for (int i = ; i < k; i++) {
if (i > ) {
printf(" ");
}
printf("%d", arr[][i]);
}
printf("\n");
}
}

1160 - X-Plosives

每次加一条边,当图中有环时不能加入。

其实就是Kruskal算法的并查集优化版,将边从小到大排序后,依次加入森林,当发现有环时跳过。其实并查集就是维护一个森林,每颗树标识着一个连通分量,每棵树有个固定的root节点,而路径压缩就是将该路径上的所有节点为根的小树都接到该连通分量的root下。

#include <iostream>
#include <stdio.h>
using namespace std; const int MAXN = 1e5 + ; class UnionSet {
public:
UnionSet() {}
UnionSet(int n) : n_(n) {
father = new int[n_];
this->init();
}
~UnionSet() {
if (NULL != father) {
delete[] father;
father = NULL;
}
}
void init() {
for (int i = ; i < n_; i++) {
father[i] = i;
}
}
/*{{{ find_father*/
int find_father(int i) {
if (father[i] == i) {
return i;
} else {
return father[i] = find_father(father[i]);
}
}
/*}}}*/
/*{{{ union_together */
bool union_together(int i, int j) {
int father_i = this->find_father(i);
int father_j = this->find_father(j);
if (father_i != father_j) {
father[father_j] = father_i;
return true;
} else {
return false;
}
}
/*}}}*/
private:
int *father;
int n_;
}; int main() {
int x, y, ans = ;
UnionSet union_set = UnionSet(MAXN);
while (scanf("%d", &x) != EOF) {
if (x == -) {
printf("%d\n", ans);
ans = ;
union_set.init();
} else {
scanf("%d", &y);
if (union_set.union_together(x, y) == false) {
ans++;
}
}
}
}

1329 - Corporative Network

查询并查集中某节点到所在连通分量根的路径长度。

每个节点维护该节点到该节点父亲的路径长度,而要求该节点到root的长度,只需在该节点处,做一个路径压缩,该节点接在了root下,也就得到了该长度。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <cmath>
using namespace std; const int MAXN = ; int father[MAXN];
// sum[i] record the sum from i to father[i]
int sum[MAXN]; int find_father(int i) {
if (i == father[i]) {
sum[i] = ;
return i;
} else {
int f = find_father(father[i]);
sum[i] += sum[father[i]];
return father[i] = f;
}
} void log(int n) {
printf("sum; ");
for (int i = ; i <= n; i++) {
find_father(i);
printf("(%d)%d ", father[i], sum[i]);
}
printf("\n");
} int main() {
int T;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
father[i] = i;
sum[i] = ;
} char ch[];
while (scanf("%s", ch)) {
if (ch[] == 'O') {
break;
} else if (ch[] == 'I') {
int a, b;
scanf("%d%d", &a, &b);
father[a] = b;
sum[a] = (int)(abs(a - b)) % ;
//log(n);
} else if (ch[] == 'E') {
int c;
scanf("%d", &c);
find_father(c);
printf("%d\n", sum[c]);
}
}
}
}

Trainning Guide, Data Structures, Example的更多相关文章

  1. Algorithms & Data structures in C++& GO ( Lock Free Queue)

    https://github.com/xtaci/algorithms //已实现 ( Implemented ): Array shuffle https://github.com/xtaci/al ...

  2. Important Abstractions and Data Structures

    For Developers‎ > ‎Coding Style‎ > ‎ Important Abstractions and Data Structures 目录 1 TaskRunne ...

  3. A library of generic data structures

    A library of generic data structures including a list, array, hashtable, deque etc.. https://github. ...

  4. The Swiss Army Knife of Data Structures … in C#

    "I worked up a full implementation as well but I decided that it was too complicated to post in ...

  5. 剪短的python数据结构和算法的书《Data Structures and Algorithms Using Python》

    按书上练习完,就可以知道日常的用处啦 #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving wit ...

  6. Persistent Data Structures

    原文链接:http://www.codeproject.com/Articles/9680/Persistent-Data-Structures Introduction When you hear ...

  7. Go Data Structures: Interfaces

    refer:http://research.swtch.com/interfaces Go Data Structures: Interfaces Posted on Tuesday, Decembe ...

  8. Choose Concurrency-Friendly Data Structures

    What is a high-performance data structure? To answer that question, we're used to applying normal co ...

  9. 无锁数据结构(Lock-Free Data Structures)

    一个星期前,我写了关于SQL Server里闩锁(Latches)和自旋锁(Spinlocks)的文章.2个同步原语(synchronization primitives)是用来保护SQL Serve ...

随机推荐

  1. c#基础------------静态类与非静态类

    呵呵,静态类,静态构造函数,静态字段,静态属性和静态方法.既然是静,那就顾其名思其意吧. 静态成员主要包括静态字段和静态属性,静态成员可以实现类中能够被所有实例对象共享的数据.静态成员属于类所有,无论 ...

  2. Codevs 5126 推销员 2015年NOIP全国联赛普及组

    5126 推销员 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死 ...

  3. poj 2220 Sumsets

                                                                                                     Sum ...

  4. 学习C++ Primer 的个人理解(一)

    <C++ Primer>这本书可以说是公认的学习C++最好的书,但我觉得不是特别适合作为教材,书中内容的顺序让人有些蛋疼.我个人认为初学此书是不能跳着看的.如果急于上手的话,我更推荐< ...

  5. java运算符新用法和^新认识

    public class Demo1 { public static void main(String[] args) { boolean t = false | true; System.out.p ...

  6. 谷歌浏览器支持小于12px的字体

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  7. 【Winform】 无法将类型为“System.Windows.Forms.SplitContainer”的对象强制转换为类型“System.ComponentModel.ISupportInitialize”。

    问题:将dotnet framework 4.0 切换到2.0时,编译没有问题,在运行时出现如下错误:System.InvalidCastException: 无法将类型为“System.Window ...

  8. 【Sqlserver】修改数据库表中的数据:对缺失的数据根据已有的数据进行修补

    1 --查询时间范围内的数据 select * from dbo.point where wtime >'2014-05-01 23:59:59' and wtime< '2014-05- ...

  9. Using jQuery to add a dynamic “Back To Top” floating button with smooth scroll

    Ever read a really long blog post or article and then had to scroll all the way up to the top of the ...

  10. CodeForces 492B

    Description Vanya walks late at night along a straight street of length l, lit by n lanterns. Consid ...