14097: 【原4097】简单链表
题目
题目描述
author: kikyou 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4097
【试题描述】
给定一个N个数的数组,M次操作,每次操作为下列操作之一。求最后的数组。
操作1:在第X个数之后插入一个数Y。
操作2:删除第X个数。
【输入要求】
第一行两个整数N,M(N,M≤100000)含义见试题描述。
第二行N个整数,表示原来的数组。
接下来M行,每行第一个数OPT,表示操作类型。
对于操作1,接下来两个数X,Y,含义见题面描述,保证0≤X≤当前数的个数,若X=0,表示在数组开头插入。
对于操作2,接下来一个数X,含义见题面描述,保证1≤X≤当前数的个数。
【输出要求】
输出若干个数,表示最后的数组。
【输入样例】
5 3 1 2 3 4 5 1 1 6 2 1 2 2
【输出样例】
6 3 4 5
FineArtz's solution
/* 简单链表 */
#include <iostream>
#include <cmath>
using namespace std;
const int MAXS = 1000;
int n, m, maxs;
class Block{
public:
Block *prev = nullptr, *next = nullptr;
int data[MAXS];
int len = 0;
Block(Block *p = nullptr, Block *q = nullptr) : prev(p), next(q) {}
void split(int pos){
if (pos >= len || pos < 0)
return;
Block *b = new Block(this, next);
if (next != nullptr)
next->prev = b;
next = b;
b->len = len - pos;
for (int i = 0; i < len - pos; ++i)
b->data[i] = data[i + pos];
len = pos;
}
bool merge(){
Block *b = next;
if (b == nullptr)
return false;
if (len + b->len > maxs)
return false;
next = b->next;
if (next != nullptr)
next->prev = this;
for (int i = 0; i < b->len; ++i)
data[len++] = b->data[i];
delete b;
return true;
}
void delNext(){
Block *b = next;
if (b == nullptr)
return;
next = b->next;
if (next != nullptr)
next->prev = this;
delete b;
}
};
ostream &operator <<(ostream &os, const Block &b){
for (int i = 0; i < b.len; ++i)
os << b.data[i] << ' ';
return os;
}
Block *head = new Block();
void insert(int x, int y){
Block *p = head->next;
while (p && x > p->len){
x -= p->len;
p = p->next;
}
p->split(x);
p->data[p->len++] = y;
}
void remove(int x){
Block *p = head->next;
while (p && x > p->len){
x -= p->len;
p = p->next;
}
p->split(x);
--p->len;
}
void maintain(){
Block *p = head->next;
while (p){
p->merge();
p = p->next;
}
}
int main(){
cin >> n >> m;
maxs = (int)(sqrt(n)) + 1;
Block *p = head->next = new Block();
for (int i = 1; i <= n; ++i){
int t;
cin >> t;
p->data[p->len++] = t;
if (p->len == maxs){
p->next = new Block();
p = p->next;
}
}
while (m--){
int op;
cin >> op;
if (op == 1){
int x, y;
cin >> x >> y;
insert(x, y);
}
else{
int x;
cin >> x;
remove(x);
}
maintain();
}
p = head->next;
while (p){
cout << *p;
p = p->next;
}
cout << endl;
return 0;
}
ligongzzz's solution
#include "iostream"
#include "vector"
#include "cmath"
using namespace std;
template <class T>
class block_node {
public:
vector<T> val;
block_node<T>* next = nullptr;
block_node<T>* last = nullptr;
size_t len = 0;
};
template <class T>
class block_list {
public:
block_node<T>* head = nullptr;
block_node<T>* rear = nullptr;
size_t _size = 0;
block_list() {
head = new block_node<T>;
rear = new block_node<T>;
head->next = rear;
rear->last = head;
_size = 0;
}
//从数组导入
void from_array(T* array_data, size_t array_size) {
_size = array_size;
auto block_size = (size_t)sqrt(array_size);
auto p = head;
for (size_t i = 0; i < array_size; i += block_size) {
p->next = new block_node<T>;
p->next->last = p;
p = p->next;
for (size_t j = 0; j < block_size && i + j < array_size; ++j) {
p->val.push_back(array_data[i + j]);
++p->len;
}
}
p->next = rear;
rear->last = p;
}
//查找
T& find(unsigned int pos) {
auto p = head;
unsigned int i = 0;
for (; i + p->len <= pos; i += p->len, p = p->next);
return p->val[pos - i];
}
//插入
void insert(unsigned int pos, const T& val) {
auto p = head;
unsigned int i = 0;
for (; i + p->len <= pos && p->next->next; i += p->len, p = p->next);
++p->len;
++_size;
p->val.insert(p->val.begin() + (pos - i), val);
//判断是否超限
auto block_size = (size_t)sqrt(_size);
if (p->len > 2 * block_size) {
auto temp = new block_node<T>;
temp->val.assign(p->val.begin() + p->len / 2, p->val.end());
p->val.erase(p->val.begin() + p->len / 2, p->val.end());
temp->len = p->len - p->len / 2;
p->len /= 2;
p->next->last = temp;
temp->next = p->next;
p->next = temp;
temp->last = p;
}
}
//删除
void erase(unsigned int pos) {
auto p = head;
unsigned int i = 0;
for (; i + p->len <= pos; i += p->len, p = p->next);
--p->len;
--_size;
p->val.erase(p->val.begin() + (pos - i));
//判断是否完全删除
if (p->len <= 0) {
p->last->next = p->next;
p->next->last = p->last;
delete p;
return;
}
//判断是否太小
auto block_size = (size_t)sqrt(_size);
if (p->len + p->next->len < block_size && p->next != rear) {
//合并
p->val.insert(p->val.end(), p->next->val.begin(), p->next->val.end());
p->len += p->next->len;
auto temp = p->next;
p->next = p->next->next;
p->next->last = p;
delete temp;
}
}
//打印
void println() {
for (auto p = head; p->next->next; p = p->next)
for (auto q : p->next->val)
cout << q << " ";
}
};
block_list<int> list_data;
int init_array[100009] = { 0 };
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int N, M;
cin >> N >> M;
for (int i = 0; i < N; ++i)
cin >> init_array[i];
list_data.from_array(init_array, N);
for (int i = 0; i < M; ++i) {
int opt;
cin >> opt;
if (opt == 1) {
int X, Y;
cin >> X >> Y;
list_data.insert(X, Y);
}
else {
int X;
cin >> X;
list_data.erase(X - 1);
}
}
list_data.println();
return 0;
}
q4x3's solution
/**
* 模拟
**/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
int dt[100233], N, M, op;
void insert(int x, int y) {
++ N;
for(int i = N;i > x + 1;-- i)
dt[i] = dt[i - 1];
dt[x + 1] = y;
}
void del(int x) {
-- N;
for(int i = x;i <= N;++ i)
dt[i] = dt[i + 1];
}
int main() {
scanf("%d%d", &N, &M);
for(int i = 1;i <= N;++ i)
scanf("%d", &dt[i]);
for(int i = 0;i < M;++ i) {
scanf("%d", &op);
if(op == 1) {
int x, y;
scanf("%d%d", &x, &y);
insert(x, y);
} else {
int x;
scanf("%d", &x);
del(x);
}
}
for(int i = 1;i <= N;++ i)
printf("%d ", dt[i]);
printf("\n");
}
victrid's solution
#include <cstdio>
#include <iostream>
#ifndef __CHUCKSIZE__
#define __CHUCKSIZE__ 256
#endif
#ifndef __CHECKVALVE__
#define __CHECKVALVE__ 1
#endif
namespace sjtu {
template <typename T>
class deque {
private:
struct node {
T* data;
node *last, *next;
node() : data(nullptr), last(nullptr), next(nullptr) {}
node(node* last, node* next) : data(nullptr), last(last), next(next) {}
node(const T& data) : last(nullptr), next(nullptr), data(new T(data)) {}
node(const node& other) : last(nullptr), next(nullptr) {
if (other.data != nullptr) {
data = new T(*(other.data));
} else
data = nullptr;
}
~node() {
if (data != nullptr)
delete data;
}
};
struct block {
size_t size;
node *head,
*tail;
block *last,
*next;
block() : size(0), head(new node()), tail(new node()), last(nullptr), next(nullptr) {
head->next = tail;
tail->last = head;
}
block(const block& other) : head(new node()), tail(new node()), size(other.size), last(nullptr), next(nullptr) {
node *nthis = head, *nother = other.head->next, *tmp;
while (nother != other.tail) {
tmp = nthis;
nthis->next = new node(*nother);
nthis = nthis->next;
nthis->last = tmp;
nother = nother->next;
}
nthis->next = tail;
tail->last = nthis;
}
block(size_t size, node* head, node* tail, block* last, block* next) : size(size), head(head), tail(tail), last(last), next(next) {}
~block() {
node* p = head;
while (p != tail) {
p = p->next;
delete p->last;
}
delete tail;
}
//node and position
node* no_at(size_t pos) const {
node* p = head->next;
while (pos) {
p = p->next;
pos--;
}
return p;
}
T& at(size_t pos) {
return *(no_at(pos)->data);
}
size_t re_at(node* pos) const {
node* p = head->next;
size_t loc = 0;
while (p != pos) {
++loc;
p = p->next;
}
return loc;
}
//int to resolve ambiguity
void insert(const T& _data, node* at, int) {
at = at->last;
node* ins = new node(_data);
ins->next = at->next;
at->next->last = ins;
at->next = ins;
ins->last = at;
++size;
return;
}
void erase(node* at, int) {
at = at->last;
at->next = at->next->next;
delete at->next->last;
at->next->last = at;
--size;
}
void insert(const T& _data, const size_t pos) {
return insert(_data, no_at(pos), 0);
}
void push_back(const T& _data) {
return insert(_data, tail, 0);
}
void pop_back() {
erase(tail->last, 0);
}
void push_front(const T& _data) {
return insert(_data, 0);
}
void pop_front() {
erase(head->next, 0);
}
T& front() const {
return *(head->next->data);
}
T& back() const {
return *(tail->last->data);
}
//Changed _! don't work if end
//EMPTY_SAFE
void split(node* pos) {
node *left_tail, *right_head;
left_tail = new node();
right_head = new node();
left_tail->last = pos;
right_head->next = pos->next;
pos->next->last = right_head;
pos->next = left_tail;
block* ins = new block(size - this->re_at(pos) - 1, right_head, tail, this, next);
size = this->re_at(pos) + 1;
tail = left_tail;
next->last = ins;
next = ins;
}
//UNSAFE
void merge() {
tail->last->next = next->head->next;
tail->last->next->last = tail->last;
next->head->next = next->tail;
tail->last = next->tail->last;
tail->last->next = tail;
next->tail->last = next->head;
size += next->size;
next = next->next;
delete next->last;
next->last = this;
}
bool exist(node* pos) const {
node* rev = pos;
for (int i = 0; i < (size >> 1) + 3; i++) {
if (pos == tail || rev == head) {
return true;
}
if (pos == nullptr || rev == nullptr) {
return false;
}
pos = pos->next;
rev = rev->last;
}
return false;
}
};
private:
size_t _size;
block *head, *tail;
bool Collectable(size_t size) const { return size >= __CHUCKSIZE__ && (size * size >= __CHECKVALVE__ * _size); }
block* bl_at(size_t& pos) const {
block* p = head->next;
while (pos >= p->size) {
pos -= p->size;
p = p->next;
}
return p;
}
public:
class const_iterator;
class iterator {
friend class deque;
private:
deque* deq;
block* blk;
node* pos;
public:
iterator() : deq(nullptr), blk(nullptr), pos(nullptr) {}
iterator(const iterator& other) : deq(other.deq), blk(other.blk), pos(other.pos) {}
iterator(deque* deq, block* blk, node* pos) : deq(deq), blk(blk), pos(pos) {}
//Uhh. If problem I'll rewrite +-
iterator& operator+=(const int& n) {
if (n == 0)
return *this;
if (n < 0)
return (*this -= (-n));
size_t dist = n + blk->re_at(pos);
block* newblk = blk;
while (dist >= newblk->size && newblk->next != deq->tail) {
dist -= newblk->size;
newblk = newblk->next;
}
node* newpos = newblk->head->next;
while (dist) {
--dist;
newpos = newpos->next;
}
blk = newblk;
pos = newpos;
return *this;
}
iterator& operator-=(const int& n) {
if (n == 0)
return *this;
if (n < 0)
return (*this += (-n));
int dist = n - blk->re_at(pos);
block* newblk = blk;
while (dist > 0) {
newblk = newblk->last;
dist -= newblk->size;
}
dist = -dist;
node* newpos = newblk->head->next;
while (dist) {
--dist;
newpos = newpos->next;
}
blk = newblk;
pos = newpos;
return *this;
}
iterator operator+(const int& n) const {
return iterator(*this) += n;
}
iterator operator-(const int& n) const {
return iterator(*this) -= n;
}
//DEST
int operator-(const iterator& rhs) const {
if (deq != rhs.deq) {
return -1;
}
size_t index = blk->re_at(pos), rindex = rhs.blk->re_at(rhs.pos);
block *lp = blk, *rp = rhs.blk, *tmp = deq->head->next;
while (tmp != lp) {
index += tmp->size;
tmp = tmp->next;
}
tmp = rhs.deq->head->next;
while (tmp != rp) {
rindex += tmp->size;
tmp = tmp->next;
}
return index - rindex;
}
//++iter
iterator& operator++() {
if (blk->next == deq->tail) {
pos = pos->next;
} else if (pos->next == blk->tail) {
blk = blk->next;
pos = blk->head->next;
} else {
pos = pos->next;
}
return *this;
}
//iter++
iterator operator++(int) {
iterator p(*this);
++(*this);
return p;
}
//--iter
iterator& operator--() {
if (pos->last == blk->head) {
blk = blk->last;
pos = blk->tail->last;
} else {
pos = pos->last;
}
return *this;
}
//iter--
iterator operator--(int) {
iterator p(*this);
--(*this);
return p;
}
T& operator*() const {
return *(pos->data);
}
T* operator->() const noexcept {
return &*(*this);
}
bool operator==(const iterator& rhs) const {
return ((deq == rhs.deq) && (blk == rhs.blk) && (pos == rhs.pos));
}
bool operator==(const const_iterator& rhs) const {
return ((deq == rhs.deq) && (blk == rhs.blk) && (pos == rhs.pos));
}
bool operator!=(const iterator& rhs) const {
return ((deq != rhs.deq) || (blk != rhs.blk) || (pos != rhs.pos));
}
bool operator!=(const const_iterator& rhs) const {
return ((deq != rhs.deq) || (blk != rhs.blk) || (pos != rhs.pos));
}
};
class const_iterator {
private:
const deque* deq;
block* blk;
node* pos;
public:
const_iterator() : deq(nullptr), blk(nullptr), pos(nullptr) {}
const_iterator(const const_iterator& other) : deq(other.deq), blk(other.blk), pos(other.pos) {}
const_iterator(const iterator& other) : deq(other.deq), blk(other.blk), pos(other.pos) {}
const_iterator(const deque* deq, block* blk, node* pos) : deq(deq), blk(blk), pos(pos) {}
//Uhh. If problem I'll rewrite +-
const_iterator& operator+=(const int& n) {
if (n == 0)
return *this;
if (n < 0)
return (*this -= (-n));
size_t dist = n + blk->re_at(pos);
block* newblk = blk;
while (dist >= newblk->size && newblk->next != deq->tail) {
dist -= newblk->size;
newblk = newblk->next;
}
node* newpos = newblk->head->next;
while (dist) {
--dist;
newpos = newpos->next;
}
blk = newblk;
pos = newpos;
return *this;
}
const_iterator& operator-=(const int& n) {
if (n == 0)
return *this;
if (n < 0)
return (*this += (-n));
int dist = n - blk->re_at(pos);
block* newblk = blk;
while (dist > 0) {
newblk = newblk->last;
dist -= newblk->size;
}
dist = -dist;
node* newpos = newblk->head->next;
while (dist) {
--dist;
newpos = newpos->next;
}
blk = newblk;
pos = newpos;
return *this;
}
const_iterator operator+(const int& n) const {
return const_iterator(*this) += n;
}
const_iterator operator-(const int& n) const {
return const_iterator(*this) -= n;
}
//DIST
int operator-(const const_iterator& rhs) const {
size_t index = blk->re_at(pos), rindex = rhs.blk->re_at(rhs.pos);
block *lp = blk, *rp = rhs.blk, *tmp = deq->head->next;
while (tmp != lp) {
index += tmp->size;
tmp = tmp->next;
}
tmp = rhs.deq->head->next;
while (tmp != rp) {
rindex += tmp->size;
tmp = tmp->next;
}
return index - rindex;
}
const_iterator& operator++() {
if (blk->next == deq->tail) {
pos = pos->next;
} else if (pos->next == blk->tail) {
blk = blk->next;
pos = blk->head->next;
} else {
pos = pos->next;
}
return *this;
}
//????Why I use const_ it SEGSIGV?
const_iterator operator++(int) {
iterator p(deq, blk, pos);
++(*this);
return p;
}
const_iterator& operator--() {
if (pos->last == blk->head) {
blk = blk->last;
pos = blk->tail->last;
} else {
pos = pos->last;
}
return *this;
}
const_iterator operator--(int) {
iterator p(deq, blk, pos);
--(*this);
return p;
}
T& operator*() const {
return *(pos->data);
}
T* operator->() const noexcept {
return &*(*this);
}
bool operator==(const iterator& rhs) const {
return ((deq == rhs.deq) && (blk == rhs.blk) && (pos == rhs.pos));
}
bool operator==(const const_iterator& rhs) const {
return ((deq == rhs.deq) && (blk == rhs.blk) && (pos == rhs.pos));
}
bool operator!=(const iterator& rhs) const {
return ((deq != rhs.deq) || (blk != rhs.blk) || (pos != rhs.pos));
}
bool operator!=(const const_iterator& rhs) const {
return ((deq != rhs.deq) || (blk != rhs.blk) || (pos != rhs.pos));
}
};
deque() : _size(0), head(new block()), tail(new block()) {
block* first = new block();
head->next = first;
first->last = head;
first->next = tail;
tail->last = first;
}
deque(const deque& other) : _size(other._size), head(new block()), tail(new block()) {
block *nthis = head, *nother = other.head->next, *tmp;
while (nother != other.tail) {
tmp = nthis;
nthis->next = new block(*nother);
nthis = nthis->next;
nthis->last = tmp;
nother = nother->next;
}
nthis->next = tail;
tail->last = nthis;
}
~deque() {
block* b = head;
while (b != tail) {
b = b->next;
delete b->last;
}
delete tail;
}
deque& operator=(const deque& other) {
if (&other == this)
return *this;
_size = other._size;
block *bthis = head->next, *bother = (other.head)->next, *tmp;
while (bthis != tail) {
tmp = bthis;
bthis = bthis->next;
delete tmp;
}
bthis = head;
while (bother != other.tail) {
tmp = bthis;
bthis->next = new block(*bother);
bthis = bthis->next;
bthis->last = tmp;
bother = bother->next;
}
bthis->next = tail;
tail->last = bthis;
return *this;
}
T& at(const size_t& pos) {
size_t ppos = pos;
return bl_at(ppos)->at(ppos);
}
iterator dq_at(const size_t& pos) {
if (pos == _size)
return end();
size_t ppos = pos;
block* ats = bl_at(ppos);
node* atts = ats->no_at(ppos);
return iterator(this, ats, atts);
}
const T& at(const size_t& pos) const {
size_t ppos = pos;
return bl_at(ppos)->at(ppos);
}
T& operator[](const size_t& pos) {
return at(pos);
}
const T& operator[](const size_t& pos) const {
return at(pos);
}
const T& front() const {
return head->next->front();
}
const T& back() const {
return tail->last->back();
}
iterator begin() {
return iterator(this, head->next, head->next->head->next);
}
const_iterator cbegin() const {
return const_iterator(this, head->next, head->next->head->next);
}
iterator end() {
return iterator(this, tail->last, tail->last->tail);
}
const_iterator cend() const {
return const_iterator(this, tail->last, tail->last->tail);
}
bool empty() const { return !_size; }
size_t size() const { return _size; }
void clear() {
_size = 0;
block* p = head->next;
while (p != tail) {
p = p->next;
delete p->last;
}
head->next = new block();
head->next->last = head;
head->next->next = tail;
tail->last = head->next;
}
iterator insert(iterator pos, const T& value) {
pos.blk->insert(value, pos.pos, 0);
_size++;
pos = iterator(this, pos.blk, pos.pos->last);
if (Collectable(pos.blk->size))
pos.blk->split(pos.pos);
return pos;
}
iterator erase(iterator pos) {
//lastent illegal iterator
node* pnext = pos.pos->next;
pos.blk->erase(pos.pos, 0);
--_size;
if (pnext == pos.blk->tail && pos.blk->next != pos.deq->tail) {
if (pos.blk->next != pos.deq->tail) {
pos.blk = pos.blk->next;
pos.pos = pos.blk->head->next;
return pos;
} else {
return end();
}
}
pos.pos = pnext;
//Here empty is processed.
if ((pos.blk->next != tail) && (pos.blk->size + pos.blk->next->size <= __CHUCKSIZE__))
pos.blk->merge();
return pos;
}
void push_back(const T& value) {
++_size;
block* p = tail->last;
if (Collectable(tail->last->size)) {
p->next = new block();
p->next->last = p;
p->next->next = tail;
tail->last = p->next;
p->next->push_back(value);
} else {
p->push_back(value);
}
return;
}
void pop_back() {
--_size;
tail->last->pop_back();
if (tail->last->size == 0 && tail->last->last != head) {
block* del = tail->last;
tail->last->last->next = tail;
tail->last = tail->last->last;
delete del;
}
return;
}
void push_front(const T& value) {
++_size;
block* p = head->next;
if (Collectable(p->size)) {
head->next = new block();
head->next->push_front(value);
head->next->next = p;
head->next->last = head;
head->next->next->last = head->next;
} else {
p->push_front(value);
}
}
void pop_front() {
--_size;
head->next->pop_front();
if (head->next->size == 0 && tail->last->last != head) {
block* p = head->next;
head->next = head->next->next;
head->next->last = head;
delete p;
return;
}
if ((head->next->next != tail) && ((head->next->size + head->next->next->size) < __CHUCKSIZE__)) {
head->next->merge();
}
}
};
} // namespace sjtu
int main() {
sjtu::deque<long long> deq;
int n, m, op;
long long pc, op1, op2;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
scanf("%lld", &pc);
deq.push_back(pc);
}
for (int i = 0; i < m; i++) {
scanf("%d", &op);
if (op == 1) {
scanf("%lld%lld", &op1, &op2);
deq.insert(deq.dq_at(op1), op2);
} else {
scanf("%lld", &op1);
deq.erase(deq.dq_at(op1 - 1));
}
}
for (auto it = deq.begin(); it != deq.end(); it++) {
printf("%lld ", *it);
}
return 0;
}