20240418
This commit is contained in:
818
ACMOJ-1335.cpp
Normal file
818
ACMOJ-1335.cpp
Normal file
@ -0,0 +1,818 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#ifndef SJTU_VECTOR_HPP
|
||||||
|
#define SJTU_VECTOR_HPP
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <exception>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sjtu {
|
||||||
|
/**
|
||||||
|
* a data container like std::vector
|
||||||
|
* store data in a successive memory and support random access.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class vector {
|
||||||
|
static std::allocator<T> alloc;
|
||||||
|
size_t allocated_length;
|
||||||
|
size_t current_length;
|
||||||
|
T *raw_beg, *raw_end;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* you can see RandomAccessIterator at CppReference for help.
|
||||||
|
*/
|
||||||
|
class const_iterator;
|
||||||
|
class iterator {
|
||||||
|
// The following code is written for the C++ type_traits library.
|
||||||
|
// Type traits is a C++ feature for describing certain properties of a type.
|
||||||
|
// For instance, for an iterator, iterator::value_type is the type that the
|
||||||
|
// iterator points to.
|
||||||
|
// STL algorithms and containers may use these type_traits (e.g. the
|
||||||
|
// following typedef) to work properly. In particular, without the following
|
||||||
|
// code,
|
||||||
|
// @code{std::sort(iter, iter1);} would not compile.
|
||||||
|
// See these websites for more information:
|
||||||
|
// https://en.cppreference.com/w/cpp/header/type_traits
|
||||||
|
// About value_type:
|
||||||
|
// https://blog.csdn.net/u014299153/article/details/72419713 About
|
||||||
|
// iterator_category: https://en.cppreference.com/w/cpp/iterator
|
||||||
|
friend class vector<T>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T *;
|
||||||
|
using reference = T &;
|
||||||
|
using iterator_category = std::random_access_iterator_tag;
|
||||||
|
|
||||||
|
private:
|
||||||
|
vector<T> *domain;
|
||||||
|
T *raw_pointer;
|
||||||
|
iterator(vector<T> *domain, T *raw_pointer)
|
||||||
|
: domain(domain), raw_pointer(raw_pointer) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* return a new iterator which pointer n-next elements
|
||||||
|
* as well as operator-
|
||||||
|
*/
|
||||||
|
iterator operator+(const int &n) const {
|
||||||
|
iterator temp = *this;
|
||||||
|
temp.raw_pointer += n;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
iterator operator-(const int &n) const {
|
||||||
|
iterator temp = *this;
|
||||||
|
temp.raw_pointer -= n;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
// return the distance between two iterators,
|
||||||
|
// if these two iterators point to different vectors, throw
|
||||||
|
// invaild_iterator.
|
||||||
|
int operator-(const iterator &rhs) const {
|
||||||
|
return raw_pointer - rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
iterator &operator+=(const int &n) {
|
||||||
|
raw_pointer += n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
iterator &operator-=(const int &n) {
|
||||||
|
raw_pointer -= n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO iter++
|
||||||
|
*/
|
||||||
|
iterator operator++(int) {
|
||||||
|
iterator temp = *this;
|
||||||
|
raw_pointer++;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO ++iter
|
||||||
|
*/
|
||||||
|
iterator &operator++() {
|
||||||
|
raw_pointer++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO iter--
|
||||||
|
*/
|
||||||
|
iterator operator--(int) {
|
||||||
|
iterator temp = *this;
|
||||||
|
raw_pointer--;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO --iter
|
||||||
|
*/
|
||||||
|
iterator &operator--() {
|
||||||
|
raw_pointer--;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO *it
|
||||||
|
*/
|
||||||
|
T &operator*() const { return *raw_pointer; }
|
||||||
|
/**
|
||||||
|
* a operator to check whether two iterators are same (pointing to the same
|
||||||
|
* memory address).
|
||||||
|
*/
|
||||||
|
bool operator==(const iterator &rhs) const {
|
||||||
|
return raw_pointer == rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
bool operator==(const const_iterator &rhs) const {
|
||||||
|
return raw_pointer == rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* some other operator for iterator.
|
||||||
|
*/
|
||||||
|
bool operator!=(const iterator &rhs) const {
|
||||||
|
return raw_pointer != rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
bool operator!=(const const_iterator &rhs) const {
|
||||||
|
return raw_pointer != rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* has same function as iterator, just for a const object.
|
||||||
|
*/
|
||||||
|
class const_iterator {
|
||||||
|
friend class vector<T>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T *;
|
||||||
|
using reference = T &;
|
||||||
|
using iterator_category = std::random_access_iterator_tag;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const vector<T> *domain;
|
||||||
|
const T *raw_pointer;
|
||||||
|
inline const_iterator(const vector<T> *domain, const T *raw_pointer)
|
||||||
|
: domain(domain), raw_pointer(raw_pointer) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* return a new iterator which pointer n-next elements
|
||||||
|
* as well as operator-
|
||||||
|
*/
|
||||||
|
const_iterator operator+(const int &n) const {
|
||||||
|
const_iterator temp = *this;
|
||||||
|
temp.raw_pointer += n;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
const_iterator operator-(const int &n) const {
|
||||||
|
const_iterator temp = *this;
|
||||||
|
temp.raw_pointer -= n;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
// return the distance between two iterators,
|
||||||
|
// if these two iterators point to different vectors, throw
|
||||||
|
// invaild_iterator.
|
||||||
|
int operator-(const const_iterator &rhs) const {
|
||||||
|
return raw_pointer - rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
const_iterator &operator+=(const int &n) {
|
||||||
|
raw_pointer += n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const_iterator &operator-=(const int &n) {
|
||||||
|
raw_pointer -= n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO iter++
|
||||||
|
*/
|
||||||
|
const_iterator operator++(int) {
|
||||||
|
const_iterator temp = *this;
|
||||||
|
raw_pointer++;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO ++iter
|
||||||
|
*/
|
||||||
|
const_iterator &operator++() {
|
||||||
|
raw_pointer++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO iter--
|
||||||
|
*/
|
||||||
|
const_iterator operator--(int) {
|
||||||
|
const_iterator temp = *this;
|
||||||
|
raw_pointer--;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO --iter
|
||||||
|
*/
|
||||||
|
const_iterator &operator--() {
|
||||||
|
raw_pointer--;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO *it
|
||||||
|
*/
|
||||||
|
const T &operator*() const { return *raw_pointer; }
|
||||||
|
/**
|
||||||
|
* a operator to check whether two iterators are same (pointing to the same
|
||||||
|
* memory address).
|
||||||
|
*/
|
||||||
|
bool operator==(const iterator &rhs) const {
|
||||||
|
return raw_pointer == rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
bool operator==(const const_iterator &rhs) const {
|
||||||
|
return raw_pointer == rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* some other operator for iterator.
|
||||||
|
*/
|
||||||
|
bool operator!=(const iterator &rhs) const {
|
||||||
|
return raw_pointer != rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
bool operator!=(const const_iterator &rhs) const {
|
||||||
|
return raw_pointer != rhs.raw_pointer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* TODO Constructs
|
||||||
|
* At least two: default constructor, copy constructor
|
||||||
|
*/
|
||||||
|
vector() {
|
||||||
|
raw_beg = alloc.allocate(1);
|
||||||
|
raw_end = raw_beg;
|
||||||
|
allocated_length = 1;
|
||||||
|
current_length = 0;
|
||||||
|
}
|
||||||
|
vector(const vector &other) {
|
||||||
|
raw_beg = alloc.allocate(other.allocated_length);
|
||||||
|
raw_end = raw_beg + other.current_length;
|
||||||
|
allocated_length = other.allocated_length;
|
||||||
|
current_length = other.current_length;
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(alloc, raw_beg + i,
|
||||||
|
other.raw_beg[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector(vector &&other) noexcept {
|
||||||
|
raw_beg = other.raw_beg;
|
||||||
|
raw_end = other.raw_end;
|
||||||
|
allocated_length = other.allocated_length;
|
||||||
|
current_length = other.current_length;
|
||||||
|
other.raw_beg = nullptr;
|
||||||
|
other.raw_end = nullptr;
|
||||||
|
other.allocated_length = 0;
|
||||||
|
other.current_length = 0;
|
||||||
|
}
|
||||||
|
~vector() {
|
||||||
|
if (raw_beg != nullptr) {
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO Assignment operator
|
||||||
|
*/
|
||||||
|
vector &operator=(const vector &other) {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
if (raw_beg != nullptr) {
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
}
|
||||||
|
raw_beg = alloc.allocate(other.allocated_length);
|
||||||
|
raw_end = raw_beg + other.current_length;
|
||||||
|
allocated_length = other.allocated_length;
|
||||||
|
current_length = other.current_length;
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(alloc, raw_beg + i,
|
||||||
|
other.raw_beg[i]);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
vector &operator=(vector &&other) noexcept {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
if (raw_beg != nullptr) {
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
}
|
||||||
|
raw_beg = other.raw_beg;
|
||||||
|
raw_end = other.raw_end;
|
||||||
|
allocated_length = other.allocated_length;
|
||||||
|
current_length = other.current_length;
|
||||||
|
other.raw_beg = nullptr;
|
||||||
|
other.raw_end = nullptr;
|
||||||
|
other.allocated_length = 0;
|
||||||
|
other.current_length = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* assigns specified element with bounds checking
|
||||||
|
* throw index_out_of_bound if pos is not in [0, size)
|
||||||
|
*/
|
||||||
|
T &at(const size_t &pos) { return raw_beg[pos]; }
|
||||||
|
const T &at(const size_t &pos) const { return raw_beg[pos]; }
|
||||||
|
/**
|
||||||
|
* assigns specified element with bounds checking
|
||||||
|
* throw index_out_of_bound if pos is not in [0, size)
|
||||||
|
* !!! Pay attentions
|
||||||
|
* In STL this operator does not check the boundary but I want you to do.
|
||||||
|
*/
|
||||||
|
T &operator[](const size_t &pos) { return raw_beg[pos]; }
|
||||||
|
const T &operator[](const size_t &pos) const { return raw_beg[pos]; }
|
||||||
|
/**
|
||||||
|
* access the first element.
|
||||||
|
* throw container_is_empty if size == 0
|
||||||
|
*/
|
||||||
|
const T &front() const { return raw_beg[0]; }
|
||||||
|
/**
|
||||||
|
* access the last element.
|
||||||
|
* throw container_is_empty if size == 0
|
||||||
|
*/
|
||||||
|
const T &back() const { return raw_end[-1]; }
|
||||||
|
/**
|
||||||
|
* returns an iterator to the beginning.
|
||||||
|
*/
|
||||||
|
iterator begin() { return iterator(this, raw_beg); }
|
||||||
|
const_iterator cbegin() const { return const_iterator(this, raw_beg); }
|
||||||
|
/**
|
||||||
|
* returns an iterator to the end.
|
||||||
|
*/
|
||||||
|
iterator end() { return iterator(this, raw_end); }
|
||||||
|
const_iterator cend() const { return const_iterator(this, raw_end); }
|
||||||
|
/**
|
||||||
|
* checks whether the container is empty
|
||||||
|
*/
|
||||||
|
bool empty() const { return current_length == 0; }
|
||||||
|
/**
|
||||||
|
* returns the number of elements
|
||||||
|
*/
|
||||||
|
size_t size() const { return current_length; }
|
||||||
|
/**
|
||||||
|
* clears the contents
|
||||||
|
*/
|
||||||
|
void clear() {
|
||||||
|
if (raw_beg != nullptr) {
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
}
|
||||||
|
raw_beg = alloc.allocate(1);
|
||||||
|
raw_end = raw_beg;
|
||||||
|
allocated_length = 1;
|
||||||
|
current_length = 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* inserts value before pos
|
||||||
|
* returns an iterator pointing to the inserted value.
|
||||||
|
*/
|
||||||
|
iterator insert(iterator pos, const T &value) {
|
||||||
|
if (current_length == allocated_length) {
|
||||||
|
size_t new_allocated_length = allocated_length * 2;
|
||||||
|
T *new_raw_beg = alloc.allocate(new_allocated_length);
|
||||||
|
pos.raw_pointer = new_raw_beg + (pos.raw_pointer - raw_beg);
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(
|
||||||
|
alloc, new_raw_beg + i, std::move(raw_beg[i]));
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
raw_beg = new_raw_beg;
|
||||||
|
raw_end = raw_beg + current_length;
|
||||||
|
allocated_length = new_allocated_length;
|
||||||
|
}
|
||||||
|
for (T *i = raw_end; i != pos.raw_pointer; --i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(alloc, i,
|
||||||
|
std::move(*(i - 1)));
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, i - 1);
|
||||||
|
}
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(alloc, pos.raw_pointer,
|
||||||
|
value);
|
||||||
|
raw_end++;
|
||||||
|
current_length++;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* inserts value at index ind.
|
||||||
|
* after inserting, this->at(ind) == value
|
||||||
|
* returns an iterator pointing to the inserted value.
|
||||||
|
* throw index_out_of_bound if ind > size (in this situation ind can be size
|
||||||
|
* because after inserting the size will increase 1.)
|
||||||
|
*/
|
||||||
|
iterator insert(const size_t &ind, const T &value) {
|
||||||
|
if (current_length == allocated_length) {
|
||||||
|
size_t new_allocated_length = allocated_length * 2;
|
||||||
|
T *new_raw_beg = alloc.allocate(new_allocated_length);
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
alloc.construct(new_raw_beg + i, std::move(raw_beg[i]));
|
||||||
|
alloc.destroy(raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
raw_beg = new_raw_beg;
|
||||||
|
raw_end = raw_beg + current_length;
|
||||||
|
allocated_length = new_allocated_length;
|
||||||
|
}
|
||||||
|
for (T *i = raw_end; i != raw_beg + ind; --i) {
|
||||||
|
alloc.construct(i, std::move(*(i - 1)));
|
||||||
|
alloc.destroy(i - 1);
|
||||||
|
}
|
||||||
|
alloc.construct(raw_beg + ind, value);
|
||||||
|
raw_end++;
|
||||||
|
current_length++;
|
||||||
|
return iterator(this, raw_beg + ind);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* removes the element at pos.
|
||||||
|
* return an iterator pointing to the following element.
|
||||||
|
* If the iterator pos refers the last element, the end() iterator is
|
||||||
|
* returned.
|
||||||
|
*/
|
||||||
|
iterator erase(iterator pos) {
|
||||||
|
for (T *i = pos.raw_pointer; i != raw_end - 1; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(alloc, i,
|
||||||
|
std::move(*(i + 1)));
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, i + 1);
|
||||||
|
}
|
||||||
|
raw_end--;
|
||||||
|
current_length--;
|
||||||
|
if (current_length != 0 && current_length <= allocated_length / 4) {
|
||||||
|
size_t new_allocated_length = allocated_length / 2;
|
||||||
|
T *new_raw_beg = alloc.allocate(new_allocated_length);
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(
|
||||||
|
alloc, new_raw_beg + i, std::move(raw_beg[i]));
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
raw_beg = new_raw_beg;
|
||||||
|
raw_end = raw_beg + current_length;
|
||||||
|
allocated_length = new_allocated_length;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* removes the element with index ind.
|
||||||
|
* return an iterator pointing to the following element.
|
||||||
|
* throw index_out_of_bound if ind >= size
|
||||||
|
*/
|
||||||
|
iterator erase(const size_t &ind) {
|
||||||
|
for (T *i = raw_beg + ind; i != raw_end - 1; ++i) {
|
||||||
|
alloc.construct(i, std::move(*(i + 1)));
|
||||||
|
alloc.destroy(i + 1);
|
||||||
|
}
|
||||||
|
raw_end--;
|
||||||
|
current_length--;
|
||||||
|
if (current_length != 0 && current_length <= allocated_length / 4) {
|
||||||
|
size_t new_allocated_length = allocated_length / 2;
|
||||||
|
T *new_raw_beg = alloc.allocate(new_allocated_length);
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
alloc.construct(new_raw_beg + i, std::move(raw_beg[i]));
|
||||||
|
alloc.destroy(raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
raw_beg = new_raw_beg;
|
||||||
|
raw_end = raw_beg + current_length;
|
||||||
|
allocated_length = new_allocated_length;
|
||||||
|
}
|
||||||
|
return iterator(this, raw_beg + ind);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* adds an element to the end.
|
||||||
|
*/
|
||||||
|
void push_back(const T &value) {
|
||||||
|
if (current_length == allocated_length) [[unlikely]] {
|
||||||
|
size_t new_allocated_length = allocated_length * 2;
|
||||||
|
T *new_raw_beg = alloc.allocate(new_allocated_length);
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(
|
||||||
|
alloc, new_raw_beg + i, std::move(raw_beg[i]));
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
raw_beg = new_raw_beg;
|
||||||
|
raw_end = raw_beg + current_length;
|
||||||
|
allocated_length = new_allocated_length;
|
||||||
|
}
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(alloc, raw_end, value);
|
||||||
|
raw_end++;
|
||||||
|
current_length++;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* remove the last element from the end.
|
||||||
|
* throw container_is_empty if size() == 0
|
||||||
|
*/
|
||||||
|
void pop_back() {
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_end - 1);
|
||||||
|
raw_end--;
|
||||||
|
current_length--;
|
||||||
|
if (current_length != 0 && current_length <= allocated_length / 4)
|
||||||
|
[[unlikely]] {
|
||||||
|
size_t new_allocated_length = allocated_length / 2;
|
||||||
|
T *new_raw_beg = alloc.allocate(new_allocated_length);
|
||||||
|
for (size_t i = 0; i < current_length; ++i) {
|
||||||
|
std::allocator_traits<decltype(alloc)>::construct(
|
||||||
|
alloc, new_raw_beg + i, std::move(raw_beg[i]));
|
||||||
|
std::allocator_traits<decltype(alloc)>::destroy(alloc, raw_beg + i);
|
||||||
|
}
|
||||||
|
alloc.deallocate(raw_beg, allocated_length);
|
||||||
|
raw_beg = new_raw_beg;
|
||||||
|
raw_end = raw_beg + current_length;
|
||||||
|
allocated_length = new_allocated_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
std::allocator<T> vector<T>::alloc;
|
||||||
|
|
||||||
|
} // namespace sjtu
|
||||||
|
|
||||||
|
#endif
|
||||||
|
typedef unsigned long long hash_t;
|
||||||
|
static inline hash_t Hash(std::string str) noexcept {
|
||||||
|
/* Reference: http://xorshift.di.unimi.it/splitmix64.c */
|
||||||
|
static const std::string salt1 = "23af0j29d";
|
||||||
|
static const std::string salt2 = "09dkl020";
|
||||||
|
constexpr static char inner_salt[17] = "si9aW@zl#2$3%4^!";
|
||||||
|
str = salt1 + str + salt2;
|
||||||
|
hash_t ret = 0;
|
||||||
|
int i = 0;
|
||||||
|
for (; i + 8 <= str.length(); i += 8) {
|
||||||
|
ret ^= *reinterpret_cast<const hash_t *>(str.c_str() + i);
|
||||||
|
ret ^= *reinterpret_cast<const hash_t *>(inner_salt + (i & 15));
|
||||||
|
ret += 0x9e3779b97f4a7c15;
|
||||||
|
ret = (ret ^ (ret >> 30)) * 0xbf58476d1ce4e5b9;
|
||||||
|
ret = (ret ^ (ret >> 27)) * 0x94d049bb133111eb;
|
||||||
|
ret ^= ret >> 31;
|
||||||
|
}
|
||||||
|
for (; i < str.length(); ++i) {
|
||||||
|
ret ^= str[i];
|
||||||
|
ret ^= inner_salt[i & 15];
|
||||||
|
ret += 0x9e3779b97f4a7c15;
|
||||||
|
ret = (ret ^ (ret >> 30)) * 0xbf58476d1ce4e5b9;
|
||||||
|
ret = (ret ^ (ret >> 27)) * 0x94d049bb133111eb;
|
||||||
|
ret ^= ret >> 31;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sjtu {
|
||||||
|
template <typename Key, typename T>
|
||||||
|
class unordered_map {
|
||||||
|
|
||||||
|
};
|
||||||
|
// implementation of unordered_map for Key = std::string
|
||||||
|
template <typename T>
|
||||||
|
class unordered_map<std::string, T> {
|
||||||
|
static const size_t kMaxBucketSize = 1 << 10;
|
||||||
|
struct Node {
|
||||||
|
std::string key;
|
||||||
|
T value;
|
||||||
|
Node *next;
|
||||||
|
Node() : next(nullptr) {}
|
||||||
|
Node(const std::string &key, const T &value, Node *next = nullptr)
|
||||||
|
: key(key), value(value), next(next) {}
|
||||||
|
};
|
||||||
|
Node *buckets[kMaxBucketSize];
|
||||||
|
size_t bucket_size;
|
||||||
|
size_t element_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unordered_map() : bucket_size(kMaxBucketSize), element_size(0) {
|
||||||
|
for (size_t i = 0; i < kMaxBucketSize; ++i) {
|
||||||
|
buckets[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~unordered_map() {
|
||||||
|
for (size_t i = 0; i < kMaxBucketSize; ++i) {
|
||||||
|
Node *cur = buckets[i];
|
||||||
|
while (cur != nullptr) {
|
||||||
|
Node *temp = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
delete temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T &operator[](const std::string &key) {
|
||||||
|
size_t hash = Hash(key) & (kMaxBucketSize - 1);
|
||||||
|
Node *cur = buckets[hash];
|
||||||
|
while (cur != nullptr) {
|
||||||
|
if (cur->key == key) return cur->value;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
cur = new Node(key, T(), buckets[hash]);
|
||||||
|
buckets[hash] = cur;
|
||||||
|
element_size++;
|
||||||
|
return cur->value;
|
||||||
|
}
|
||||||
|
T &at(const std::string &key) {
|
||||||
|
size_t hash = Hash(key) & (kMaxBucketSize - 1);
|
||||||
|
Node *cur = buckets[hash];
|
||||||
|
while (cur != nullptr) {
|
||||||
|
if (cur->key == key) return cur->value;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
throw std::out_of_range("Key not found");
|
||||||
|
}
|
||||||
|
const T &at(const std::string &key) const {
|
||||||
|
size_t hash = Hash(key) & (kMaxBucketSize - 1);
|
||||||
|
Node *cur = buckets[hash];
|
||||||
|
while (cur != nullptr) {
|
||||||
|
if (cur->key == key) return cur->value;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
throw std::out_of_range("Key not found");
|
||||||
|
}
|
||||||
|
size_t count(const std::string &key) const {
|
||||||
|
size_t hash = Hash(key) & (kMaxBucketSize - 1);
|
||||||
|
Node *cur = buckets[hash];
|
||||||
|
while (cur != nullptr) {
|
||||||
|
if (cur->key == key) return 1;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void erase(const std::string &key) {
|
||||||
|
size_t hash = Hash(key) & (kMaxBucketSize - 1);
|
||||||
|
Node *cur = buckets[hash];
|
||||||
|
if (cur == nullptr) return;
|
||||||
|
if (cur->key == key) {
|
||||||
|
buckets[hash] = cur->next;
|
||||||
|
delete cur;
|
||||||
|
element_size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (cur->next != nullptr) {
|
||||||
|
if (cur->next->key == key) {
|
||||||
|
Node *temp = cur->next;
|
||||||
|
cur->next = cur->next->next;
|
||||||
|
delete temp;
|
||||||
|
element_size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void clear() {
|
||||||
|
for (size_t i = 0; i < kMaxBucketSize; ++i) {
|
||||||
|
Node *cur = buckets[i];
|
||||||
|
while (cur != nullptr) {
|
||||||
|
Node *temp = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
delete temp;
|
||||||
|
}
|
||||||
|
buckets[i] = nullptr;
|
||||||
|
}
|
||||||
|
element_size = 0;
|
||||||
|
}
|
||||||
|
size_t size() const { return element_size; }
|
||||||
|
bool Have(const std::string &key) const {
|
||||||
|
size_t hash = Hash(key) & (kMaxBucketSize - 1);
|
||||||
|
Node *cur = buckets[hash];
|
||||||
|
while (cur != nullptr) {
|
||||||
|
if (cur->key == key) return true;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace sjtu
|
||||||
|
class ClassType {
|
||||||
|
public:
|
||||||
|
enum ImportType { kPublicImport, kProtectedImport, kPrivateImport };
|
||||||
|
enum StatusType {
|
||||||
|
kPublic = 4,
|
||||||
|
kProtected = 3,
|
||||||
|
kPrivate = 2,
|
||||||
|
kUnvisible = 1,
|
||||||
|
kNone = 0
|
||||||
|
};
|
||||||
|
void Import(ClassType &src, ImportType import_type) {
|
||||||
|
if (import_type == ImportType::kPublicImport) {
|
||||||
|
pub_anc.push_back(&src);
|
||||||
|
} else if (import_type == ImportType::kProtectedImport) {
|
||||||
|
prot_anc.push_back(&src);
|
||||||
|
} else {
|
||||||
|
priv_anc.push_back(&src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddElement(const std::string &name, StatusType status) {
|
||||||
|
elements[name] = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusType QueryElement(const std::string &name) {
|
||||||
|
return DFSSearch(this, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static StatusType DFSSearch(ClassType *rt, const std::string name) {
|
||||||
|
StatusType res = StatusType::kNone;
|
||||||
|
if (rt->elements.Have(name)) res = rt->elements[name];
|
||||||
|
for (int i = 0; i < rt->pub_anc.size(); i++) {
|
||||||
|
StatusType sub_res = DFSSearch(rt->pub_anc[i], name);
|
||||||
|
if (sub_res == StatusType::kPrivate) sub_res = StatusType::kUnvisible;
|
||||||
|
res = (sub_res > res) ? sub_res : res;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < rt->prot_anc.size(); i++) {
|
||||||
|
StatusType sub_res = DFSSearch(rt->prot_anc[i], name);
|
||||||
|
if (sub_res == StatusType::kPrivate) sub_res = StatusType::kUnvisible;
|
||||||
|
if ((sub_res == StatusType::kPublic) ||
|
||||||
|
(sub_res == StatusType::kProtected))
|
||||||
|
sub_res = StatusType::kProtected;
|
||||||
|
res = (sub_res > res) ? sub_res : res;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < rt->priv_anc.size(); i++) {
|
||||||
|
StatusType sub_res = DFSSearch(rt->priv_anc[i], name);
|
||||||
|
if (sub_res == StatusType::kPrivate) sub_res = StatusType::kUnvisible;
|
||||||
|
if ((sub_res == StatusType::kPublic) ||
|
||||||
|
(sub_res == StatusType::kProtected))
|
||||||
|
sub_res = StatusType::kPrivate;
|
||||||
|
res = (sub_res > res) ? sub_res : res;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjtu::unordered_map<std::string, StatusType> elements;
|
||||||
|
sjtu::vector<ClassType *> pub_anc, prot_anc, priv_anc;
|
||||||
|
};
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif // ifdef local
|
||||||
|
int n;
|
||||||
|
sjtu::unordered_map<std::string, ClassType> class_registery;
|
||||||
|
std::cin >> n;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
std::string name;
|
||||||
|
std::cin >> name;
|
||||||
|
class_registery[name];
|
||||||
|
int k0;
|
||||||
|
std::cin >> k0;
|
||||||
|
for (int j = 0; j < k0; j++) {
|
||||||
|
std::string method, srcname;
|
||||||
|
std::cin >> method >> srcname;
|
||||||
|
if (method == "public")
|
||||||
|
class_registery[name].Import(class_registery[srcname],
|
||||||
|
ClassType::ImportType::kPublicImport);
|
||||||
|
else if (method == "private")
|
||||||
|
class_registery[name].Import(class_registery[srcname],
|
||||||
|
ClassType::ImportType::kPrivateImport);
|
||||||
|
else
|
||||||
|
class_registery[name].Import(class_registery[srcname],
|
||||||
|
ClassType::ImportType::kProtectedImport);
|
||||||
|
}
|
||||||
|
int k1;
|
||||||
|
std::cin >> k1;
|
||||||
|
for (int j = 0; j < k1; j++) {
|
||||||
|
std::string mode, element_name;
|
||||||
|
std::cin >> mode >> element_name;
|
||||||
|
if (mode == "public")
|
||||||
|
class_registery[name].AddElement(element_name,
|
||||||
|
ClassType::StatusType::kPublic);
|
||||||
|
else if (mode == "private")
|
||||||
|
class_registery[name].AddElement(element_name,
|
||||||
|
ClassType::StatusType::kPrivate);
|
||||||
|
else
|
||||||
|
class_registery[name].AddElement(element_name,
|
||||||
|
ClassType::StatusType::kProtected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int m;
|
||||||
|
std::cin >> m;
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
std::string class_name, element_name;
|
||||||
|
std::cin >> class_name >> element_name;
|
||||||
|
ClassType::StatusType stat =
|
||||||
|
class_registery[class_name].QueryElement(element_name);
|
||||||
|
switch (stat) {
|
||||||
|
case ClassType::StatusType::kNone:
|
||||||
|
std::cout << "None\n";
|
||||||
|
break;
|
||||||
|
case ClassType::StatusType::kPrivate:
|
||||||
|
std::cout << "Private\n";
|
||||||
|
break;
|
||||||
|
case ClassType::StatusType::kProtected:
|
||||||
|
std::cout << "Protected\n";
|
||||||
|
break;
|
||||||
|
case ClassType::StatusType::kPublic:
|
||||||
|
std::cout << "Public\n";
|
||||||
|
break;
|
||||||
|
case ClassType::StatusType::kUnvisible:
|
||||||
|
std::cout << "Can not Fetch\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
94
ACMOJ-1381.cpp
Normal file
94
ACMOJ-1381.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unordered_map>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef uint64_t hash_t;
|
||||||
|
static inline hash_t Hash(char *str, int len) noexcept {
|
||||||
|
/* Reference: http://xorshift.di.unimi.it/splitmix64.c */
|
||||||
|
hash_t ret = 0;
|
||||||
|
static char inner_salt[17] = "si9aW@zl#2$3%4^!";
|
||||||
|
int i = 0;
|
||||||
|
for (; i + 8 <= len; i += 8) {
|
||||||
|
ret ^= *reinterpret_cast<const hash_t *>(str + i);
|
||||||
|
ret ^= *reinterpret_cast<const hash_t *>(inner_salt + (i & 15));
|
||||||
|
ret += 0x9e3779b97f4a7c15;
|
||||||
|
ret = (ret ^ (ret >> 30)) * 0xbf58476d1ce4e5b9;
|
||||||
|
ret = (ret ^ (ret >> 27)) * 0x94d049bb133111eb;
|
||||||
|
ret ^= ret >> 31;
|
||||||
|
}
|
||||||
|
for (; i < len; ++i) {
|
||||||
|
ret ^= str[i];
|
||||||
|
ret ^= inner_salt[i & 15];
|
||||||
|
ret += 0x9e3779b97f4a7c15;
|
||||||
|
ret = (ret ^ (ret >> 30)) * 0xbf58476d1ce4e5b9;
|
||||||
|
ret = (ret ^ (ret >> 27)) * 0x94d049bb133111eb;
|
||||||
|
ret ^= ret >> 31;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
const int kMaxN = 1005;
|
||||||
|
const int kMaxM = 1e5 + 10;
|
||||||
|
int n, m;
|
||||||
|
unordered_map<hash_t, int> wanted, cnt;
|
||||||
|
hash_t paragraph[kMaxM];
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
char tmp[15];
|
||||||
|
scanf("%d", &n);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
scanf("%s", tmp);
|
||||||
|
wanted[Hash(tmp, strlen(tmp))] = 1;
|
||||||
|
}
|
||||||
|
scanf("%d", &m);
|
||||||
|
int count_needed = 0;
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
scanf("%s", tmp);
|
||||||
|
paragraph[i] = Hash(tmp, strlen(tmp));
|
||||||
|
if (wanted.find(paragraph[i]) != wanted.end() &&
|
||||||
|
wanted[paragraph[i]] == 1) {
|
||||||
|
count_needed++;
|
||||||
|
wanted[paragraph[i]] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("%d\n", count_needed);
|
||||||
|
int L = 0, R = -1, current_have = 0;
|
||||||
|
while (current_have < count_needed) {
|
||||||
|
R++;
|
||||||
|
if (wanted.find(paragraph[R]) != wanted.end()) {
|
||||||
|
cnt[paragraph[R]]++;
|
||||||
|
if (cnt[paragraph[R]] == 1) current_have++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (L <= R) {
|
||||||
|
if (wanted.find(paragraph[L]) == wanted.end()) {
|
||||||
|
L++;
|
||||||
|
} else if (cnt[paragraph[L]] >= 2) {
|
||||||
|
cnt[paragraph[L]]--;
|
||||||
|
L++;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int res = R - L + 1;
|
||||||
|
while (R + 1 < m) {
|
||||||
|
R++;
|
||||||
|
if (wanted.find(paragraph[R]) != wanted.end()) {
|
||||||
|
cnt[paragraph[R]]++;
|
||||||
|
while (L <= R) {
|
||||||
|
if (wanted.find(paragraph[L]) == wanted.end()) {
|
||||||
|
L++;
|
||||||
|
} else if (cnt[paragraph[L]] >= 2) {
|
||||||
|
cnt[paragraph[L]]--;
|
||||||
|
L++;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = min(res, R - L + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("%d\n", res);
|
||||||
|
return 0;
|
||||||
|
}
|
29
ACMOJ-1477.cpp
Normal file
29
ACMOJ-1477.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stack>
|
||||||
|
using namespace std;
|
||||||
|
const int kMaxN = 1e6 + 10;
|
||||||
|
char s[kMaxN];
|
||||||
|
int len = 0;
|
||||||
|
int Next[kMaxN];
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%s", s + 1);
|
||||||
|
len = strlen(s + 1);
|
||||||
|
for (int i = 2, j = 0; i <= len; i++) {
|
||||||
|
while (j > 0 && s[i] != s[j + 1]) j = Next[j];
|
||||||
|
if (s[i] == s[j + 1]) j++;
|
||||||
|
Next[i] = j;
|
||||||
|
}
|
||||||
|
stack<int> res;
|
||||||
|
for (int p = len; p > 0; p = Next[p]) res.push(p);
|
||||||
|
while(!res.empty())
|
||||||
|
{
|
||||||
|
printf("%d\n",res.top());
|
||||||
|
res.pop();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
28
ACMOJ-1507.cpp
Normal file
28
ACMOJ-1507.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
const int kMaxN = 1e6 + 10;
|
||||||
|
char S[kMaxN], T[kMaxN];
|
||||||
|
int nxt[kMaxN];
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%s%s", S + 1, T + 1);
|
||||||
|
int len_T = strlen(T + 1);
|
||||||
|
for (int i = 2, j = 0; i <= len_T; i++) {
|
||||||
|
while (j > 0 && T[j + 1] != T[i]) j = nxt[j];
|
||||||
|
if (T[j + 1] == T[i]) j++;
|
||||||
|
nxt[i] = j;
|
||||||
|
}
|
||||||
|
int len_S = strlen(S + 1);
|
||||||
|
for (int i = 1, j = 0; i <= len_S; i++) {
|
||||||
|
while (j > 0 && (j == len_T || T[j + 1] != S[i])) j = nxt[j];
|
||||||
|
if (T[j + 1] == S[i]) j++;
|
||||||
|
if (j == len_T) printf("%d\n", i - len_T + 1);
|
||||||
|
}
|
||||||
|
for (int i = 1; i <= len_T; i++) printf("%d ", nxt[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
100
ACMOJ-1812.cpp
Normal file
100
ACMOJ-1812.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
template <typename T>
|
||||||
|
void MergeSort(T *beg, T *end, bool (*cmp)(const T &, const T &)) {
|
||||||
|
if (end - beg <= 1) return;
|
||||||
|
size_t len = end - beg;
|
||||||
|
T *mid = beg + (len >> 1);
|
||||||
|
MergeSort(beg, mid, cmp);
|
||||||
|
MergeSort(mid, end, cmp);
|
||||||
|
T *tmp = new T[len];
|
||||||
|
T *cur_tmp = tmp, *cur_L = beg, *cur_R = mid;
|
||||||
|
while ((cur_L < mid) && (cur_R < end)) {
|
||||||
|
if (cmp(*cur_L, *cur_R))
|
||||||
|
*(cur_tmp++) = *(cur_L++);
|
||||||
|
else
|
||||||
|
*(cur_tmp++) = *(cur_R++);
|
||||||
|
}
|
||||||
|
while (cur_L < mid) *(cur_tmp++) = *(cur_L++);
|
||||||
|
while (cur_R < end) *(cur_tmp++) = *(cur_R++);
|
||||||
|
cur_tmp = tmp;
|
||||||
|
T *cur_dst = beg;
|
||||||
|
while (cur_dst < end) *(cur_dst++) = *(cur_tmp++);
|
||||||
|
delete[] tmp;
|
||||||
|
}
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 5e4 + 10;
|
||||||
|
const int kMaxM = 1e5 + 10;
|
||||||
|
int n, m, K;
|
||||||
|
struct Edge {
|
||||||
|
int u, v, w;
|
||||||
|
bool is_white;
|
||||||
|
} edge[kMaxM];
|
||||||
|
int penalty_for_white;
|
||||||
|
bool Cmp(const Edge &A, const Edge &B) {
|
||||||
|
int wa = (A.is_white ? A.w + penalty_for_white : A.w);
|
||||||
|
int wb = (B.is_white ? B.w + penalty_for_white : B.w);
|
||||||
|
if (wa == wb) return (int)A.is_white > (int)B.is_white;
|
||||||
|
return wa < wb;
|
||||||
|
}
|
||||||
|
int fa[kMaxN];
|
||||||
|
inline int ff(int u) {
|
||||||
|
int x = u, y;
|
||||||
|
while (fa[u] != u) u = fa[u];
|
||||||
|
while (x != u) {
|
||||||
|
y = fa[x];
|
||||||
|
fa[x] = u;
|
||||||
|
x = y;
|
||||||
|
}
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
void Calc(LL &res, int &white_used_count) {
|
||||||
|
white_used_count = 0;
|
||||||
|
res = 0;
|
||||||
|
MergeSort(edge, edge + m, Cmp);
|
||||||
|
for (int i = 0; i <= n; i++) fa[i] = i;
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
int u = edge[i].u;
|
||||||
|
int v = edge[i].v;
|
||||||
|
int w = edge[i].is_white ? edge[i].w + penalty_for_white : edge[i].w;
|
||||||
|
if (ff(u) == ff(v)) continue;
|
||||||
|
fa[ff(u)] = ff(v);
|
||||||
|
if (edge[i].is_white) white_used_count++;
|
||||||
|
res += w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d%d%d", &n, &m, &K);
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
int u, v, w, col;
|
||||||
|
scanf("%d%d%d%d", &u, &v, &w, &col);
|
||||||
|
edge[i] = Edge{u, v, w, bool(col == 0)};
|
||||||
|
}
|
||||||
|
int L = -110, R = 110;
|
||||||
|
LL ans = 0x3f3f3f3f3f3f3f3f;
|
||||||
|
while (L < R) {
|
||||||
|
int M = (L + R) >> 1;
|
||||||
|
penalty_for_white = M;
|
||||||
|
LL res;
|
||||||
|
int white_used_count;
|
||||||
|
Calc(res, white_used_count);
|
||||||
|
// printf("mid=%d flag=%d\n",M,int(white_used_count >= K));
|
||||||
|
if (white_used_count >= K) {
|
||||||
|
ans = res - K * (LL)penalty_for_white;
|
||||||
|
// printf("ans=%lld mid=%d\n",ans,M);
|
||||||
|
L = M + 1;
|
||||||
|
} else if (white_used_count < K) {
|
||||||
|
R = M;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0x3f3f3f3f3f3f3f3f == ans) ans = -1;
|
||||||
|
printf("%lld\n", ans);
|
||||||
|
return 0;
|
||||||
|
}
|
29
ACMOJ-2112.cpp
Normal file
29
ACMOJ-2112.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stack>
|
||||||
|
using namespace std;
|
||||||
|
const int kMaxN = 4e6 + 10;
|
||||||
|
char s[kMaxN], s_reverse[kMaxN];
|
||||||
|
int len = 0;
|
||||||
|
int Next[kMaxN];
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%s", s + 1);
|
||||||
|
len = strlen(s + 1);
|
||||||
|
for (int i = 1; i <= len; i++) s_reverse[i] = s[len + 1 - i];
|
||||||
|
for (int i = 2, j = 0; i <= len; i++) {
|
||||||
|
while (j > 0 && s_reverse[i] != s_reverse[j + 1]) j = Next[j];
|
||||||
|
if (s_reverse[i] == s_reverse[j + 1]) j++;
|
||||||
|
Next[i] = j;
|
||||||
|
}
|
||||||
|
int p = 0;
|
||||||
|
for (int i = 1; i <= len; i++) {
|
||||||
|
while (p > 0 && s[i] != s_reverse[p + 1]) p = Next[p];
|
||||||
|
if (s[i] == s_reverse[p + 1]) p++;
|
||||||
|
}
|
||||||
|
printf("%d\n", len - p);
|
||||||
|
return 0;
|
||||||
|
}
|
84
ACMOJ-2121.cpp
Normal file
84
ACMOJ-2121.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = (1 << 20) + 10;
|
||||||
|
int T;
|
||||||
|
char s[kMaxN];
|
||||||
|
int z[kMaxN];
|
||||||
|
int suf_cnt[26], pre_cnt[26];
|
||||||
|
int tot_bucket[kMaxN];
|
||||||
|
inline void Flip(char ch, int *cnt, int &occur) {
|
||||||
|
cnt[ch - 'a'] ^= 1;
|
||||||
|
if (cnt[ch - 'a'])
|
||||||
|
occur++;
|
||||||
|
else
|
||||||
|
occur--;
|
||||||
|
}
|
||||||
|
LL solve() {
|
||||||
|
int n = strlen(s);
|
||||||
|
memset(z, 0, sizeof(z));
|
||||||
|
for (int i = 1, l = 0, r = 0; i < n; ++i) {
|
||||||
|
if (i <= r && z[i - l] < r - i + 1) {
|
||||||
|
z[i] = z[i - l];
|
||||||
|
} else {
|
||||||
|
z[i] = max(0, r - i + 1);
|
||||||
|
while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i];
|
||||||
|
}
|
||||||
|
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
|
||||||
|
}
|
||||||
|
LL res = 0;
|
||||||
|
int even_A_tot = 0;
|
||||||
|
int odd_A_tot = 0;
|
||||||
|
memset(suf_cnt, 0, sizeof(suf_cnt));
|
||||||
|
for (int i = 0; i < n; i++) suf_cnt[s[i] - 'a'] ^= 1;
|
||||||
|
int all_occur_tot = 0, suf_occur_tot = 0, pre_occur_tot = 0;
|
||||||
|
for (int i = 0; i < 26; i++) all_occur_tot += suf_cnt[i];
|
||||||
|
memset(pre_cnt, 0, sizeof(pre_cnt));
|
||||||
|
suf_occur_tot = all_occur_tot;
|
||||||
|
Flip(s[0], suf_cnt, suf_occur_tot);
|
||||||
|
memset(tot_bucket, 0, sizeof(tot_bucket));
|
||||||
|
for (int i = 1; i <= n - 1; i++) {
|
||||||
|
int odd_C_tot = ceil((min(z[i], n - i - 1) / i + 1) / 2.0);
|
||||||
|
int even_C_tot = ((min(z[i], n - i - 1) / i + 1) / 2.0);
|
||||||
|
res += odd_A_tot * (LL)odd_C_tot;
|
||||||
|
res += even_A_tot * (LL)even_C_tot;
|
||||||
|
// printf("A(%d,%d)\n", odd_A_tot, odd_C_tot);
|
||||||
|
// printf("B(%d,%d)\n", even_A_tot, even_C_tot);
|
||||||
|
if (i == n - 1) break;
|
||||||
|
int old_suf_occur_tot = suf_occur_tot;
|
||||||
|
Flip(s[i], suf_cnt, suf_occur_tot);
|
||||||
|
// Flip(s[i - 1], pre_cnt, pre_occur_tot, tot_bucket);
|
||||||
|
pre_cnt[s[i - 1] - 'a'] ^= 1;
|
||||||
|
if (pre_cnt[s[i - 1] - 'a']) {
|
||||||
|
pre_occur_tot++;
|
||||||
|
} else {
|
||||||
|
pre_occur_tot--;
|
||||||
|
}
|
||||||
|
tot_bucket[pre_occur_tot]++;
|
||||||
|
if (pre_occur_tot <= old_suf_occur_tot) odd_A_tot++;
|
||||||
|
if (old_suf_occur_tot < suf_occur_tot)
|
||||||
|
odd_A_tot += tot_bucket[suf_occur_tot];
|
||||||
|
else
|
||||||
|
odd_A_tot -= tot_bucket[old_suf_occur_tot];
|
||||||
|
// printf("i=%d all_occur_tot=%d pre_occur_tot=%d suf_occur_tot=%d\n", i,
|
||||||
|
// all_occur_tot, pre_occur_tot, suf_occur_tot);
|
||||||
|
// odd_A_tot += (pre_occur_tot <= suf_occur_tot ? 1 : 0);
|
||||||
|
even_A_tot += (pre_occur_tot <= all_occur_tot ? 1 : 0);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d", &T);
|
||||||
|
while (T-- > 0) {
|
||||||
|
scanf("%s", s);
|
||||||
|
printf("%lld\n", solve());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
81
ACMOJ-2122.cpp
Normal file
81
ACMOJ-2122.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <queue>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 4e3 + 10;
|
||||||
|
struct Point {
|
||||||
|
int a, b, c;
|
||||||
|
};
|
||||||
|
int ch[2][2][kMaxN][26], fa[2][kMaxN], len[2][kMaxN];
|
||||||
|
bool vis[kMaxN][kMaxN];
|
||||||
|
int tot[2] = {1, 1}, last[2] = {1, 1};
|
||||||
|
char A[kMaxN], B[kMaxN];
|
||||||
|
void InitSequenceMachine(char *s, int flag) {
|
||||||
|
for (int i = strlen(s + 1); i; --i) {
|
||||||
|
memcpy(ch[flag][0][i - 1], ch[flag][0][i], 104);
|
||||||
|
ch[flag][0][i - 1][s[i] - 'a'] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void AddChar(int character, int string_flag) {
|
||||||
|
int p = last[string_flag], np = last[string_flag] = ++tot[string_flag];
|
||||||
|
len[string_flag][np] = len[string_flag][p] + 1;
|
||||||
|
for (; p && !ch[string_flag][1][p][character]; p = fa[string_flag][p])
|
||||||
|
ch[string_flag][1][p][character] = np;
|
||||||
|
if (!p)
|
||||||
|
fa[string_flag][np] = 1;
|
||||||
|
else {
|
||||||
|
int q = ch[string_flag][1][p][character];
|
||||||
|
if (len[string_flag][q] == len[string_flag][p] + 1)
|
||||||
|
fa[string_flag][np] = q;
|
||||||
|
else {
|
||||||
|
int nq = ++tot[string_flag];
|
||||||
|
len[string_flag][nq] = len[string_flag][p] + 1;
|
||||||
|
fa[string_flag][nq] = fa[string_flag][q];
|
||||||
|
fa[string_flag][q] = fa[string_flag][np] = nq;
|
||||||
|
memcpy(ch[string_flag][1][nq], ch[string_flag][1][q], 104);
|
||||||
|
for (; p && ch[string_flag][1][p][character] == q; p = fa[string_flag][p])
|
||||||
|
ch[string_flag][1][p][character] = nq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Solve(int flag1, int flag2) {
|
||||||
|
memset(vis, 0, sizeof(vis));
|
||||||
|
queue<Point> q;
|
||||||
|
q.push((Point){flag1, flag2, 0});
|
||||||
|
vis[flag1][flag2] = 1;
|
||||||
|
while (!q.empty()) {
|
||||||
|
Point now = q.front();
|
||||||
|
q.pop();
|
||||||
|
for (int i = 0; i < 26; ++i)
|
||||||
|
if (ch[0][flag1][now.a][i]) {
|
||||||
|
if (ch[1][flag2][now.b][i]) {
|
||||||
|
int a = ch[0][flag1][now.a][i], b = ch[1][flag2][now.b][i];
|
||||||
|
if (!vis[a][b]) vis[a][b] = 1, q.push((Point){a, b, now.c + 1});
|
||||||
|
} else {
|
||||||
|
printf("%d\n", now.c + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("-1\n");
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%s", A + 1);
|
||||||
|
scanf("%s", B + 1);
|
||||||
|
InitSequenceMachine(A, 0);
|
||||||
|
InitSequenceMachine(B, 1);
|
||||||
|
for (char *p = A + 1; *p; p++) AddChar(*p - 'a', 0);
|
||||||
|
for (char *p = B + 1; *p; p++) AddChar(*p - 'a', 1);
|
||||||
|
Solve(1, 1);
|
||||||
|
Solve(1, 0);
|
||||||
|
Solve(0, 1);
|
||||||
|
Solve(0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
316
ACMOJ-2132.cpp
Normal file
316
ACMOJ-2132.cpp
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
#include <cstdio>
|
||||||
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
struct char_reader {
|
||||||
|
FILE *f;
|
||||||
|
char *buf, *p1, *p2;
|
||||||
|
int size;
|
||||||
|
char_reader(FILE *fin, int bufsize = 1 << 16) {
|
||||||
|
f = fin;
|
||||||
|
size = bufsize;
|
||||||
|
p1 = p2 = 0;
|
||||||
|
buf = new char[size];
|
||||||
|
}
|
||||||
|
~char_reader() { delete[] buf; }
|
||||||
|
inline int operator()() {
|
||||||
|
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, size, f), p1 == p2)
|
||||||
|
? EOF
|
||||||
|
: *p1++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct char_writer {
|
||||||
|
FILE *f;
|
||||||
|
char *buf, *p, *end;
|
||||||
|
int size;
|
||||||
|
char_writer(FILE *fout, int bufsize = 1 << 16) {
|
||||||
|
f = fout;
|
||||||
|
size = bufsize;
|
||||||
|
buf = new char[size];
|
||||||
|
p = buf;
|
||||||
|
end = buf + bufsize;
|
||||||
|
}
|
||||||
|
~char_writer() {
|
||||||
|
fwrite(buf, p - buf, 1, f);
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
inline char operator()(char ch) {
|
||||||
|
if (unlikely(end == p)) {
|
||||||
|
fwrite(buf, end - buf, 1, f);
|
||||||
|
p = buf;
|
||||||
|
}
|
||||||
|
return *p++ = ch;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
char_reader gch(stdin);
|
||||||
|
char_writer wch(stdout);
|
||||||
|
template <typename T>
|
||||||
|
inline int read(T &t) {
|
||||||
|
bool f = false;
|
||||||
|
int ch;
|
||||||
|
while (ch = gch(), !((ch >= '0' && ch <= '9') || ch == '-')) {
|
||||||
|
if (ch == EOF) return 0;
|
||||||
|
}
|
||||||
|
t = 0;
|
||||||
|
if (ch == '-') f = true, ch = gch();
|
||||||
|
t = ch ^ 48;
|
||||||
|
while (ch = gch(), ch >= '0' && ch <= '9')
|
||||||
|
t = (t << 3) + (t << 1) + (ch ^ 48);
|
||||||
|
if (f) t = -t;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
inline int read(char &c) {
|
||||||
|
c = 0;
|
||||||
|
int ch;
|
||||||
|
while (ch = gch(), (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')) {
|
||||||
|
if (ch == EOF) return 0;
|
||||||
|
}
|
||||||
|
c = ch;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
inline int read(char *s) {
|
||||||
|
int ch;
|
||||||
|
while (ch = gch(), (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')) {
|
||||||
|
if (ch == EOF) return 0;
|
||||||
|
}
|
||||||
|
*s++ = ch;
|
||||||
|
while (ch = gch(),
|
||||||
|
!(ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') && ch != EOF)
|
||||||
|
*s++ = ch;
|
||||||
|
*s++ = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
inline int read(const char *s) { return read((char *)s); }
|
||||||
|
inline int readline(char *s) {
|
||||||
|
int ch;
|
||||||
|
while (ch = gch(), (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')) {
|
||||||
|
if (ch == EOF) return 0;
|
||||||
|
}
|
||||||
|
*s++ = ch;
|
||||||
|
while (ch = gch(), !(ch == '\n' || ch == '\r') && ch != EOF) *s++ = ch;
|
||||||
|
*s++ = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
inline int readline(const char *s) { return readline((char *)s); }
|
||||||
|
template <typename T>
|
||||||
|
inline void write(T t) {
|
||||||
|
int stk[20], cnt = 0;
|
||||||
|
if (t == 0) {
|
||||||
|
wch('0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (t < 0) {
|
||||||
|
wch('-');
|
||||||
|
t = -t;
|
||||||
|
}
|
||||||
|
while (t > 0) {
|
||||||
|
stk[cnt++] = t % 10;
|
||||||
|
t /= 10;
|
||||||
|
}
|
||||||
|
while (cnt) wch(stk[--cnt] + '0');
|
||||||
|
}
|
||||||
|
inline void write(char t) { wch(t); }
|
||||||
|
inline void write(char *s) {
|
||||||
|
while (*s) wch(*s++);
|
||||||
|
}
|
||||||
|
inline void write(const char *s) { write((char *)s); }
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
inline int read(T &t, Args &...args) {
|
||||||
|
return read(t) + read(args...);
|
||||||
|
}
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
inline void write(T t, Args... args) {
|
||||||
|
write(t);
|
||||||
|
write(args...);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template <typename A_t, typename B_t>
|
||||||
|
inline int read(A_t &a, B_t &b) {
|
||||||
|
return read(a) + read(b);
|
||||||
|
}
|
||||||
|
template <typename A_t, typename B_t, typename C_t>
|
||||||
|
inline int read(A_t &a, B_t &b, C_t &c) {
|
||||||
|
return read(a) + read(b) + read(c);
|
||||||
|
}
|
||||||
|
template <typename A_t, typename B_t, typename C_t, typename D_t>
|
||||||
|
inline int read(A_t &a, B_t &b, C_t &c, D_t &d) {
|
||||||
|
return read(a) + read(b) + read(c) + read(d);
|
||||||
|
}
|
||||||
|
template <typename A_t, typename B_t>
|
||||||
|
inline void write(A_t a, B_t b) {
|
||||||
|
write(a);
|
||||||
|
write(b);
|
||||||
|
}
|
||||||
|
template <typename A_t, typename B_t, typename C_t>
|
||||||
|
inline void write(A_t a, B_t b, C_t c) {
|
||||||
|
write(a);
|
||||||
|
write(b);
|
||||||
|
write(c);
|
||||||
|
}
|
||||||
|
template <typename A_t, typename B_t, typename C_t, typename D_t>
|
||||||
|
inline void write(A_t a, B_t b, C_t c, D_t d) {
|
||||||
|
write(a);
|
||||||
|
write(b);
|
||||||
|
write(c);
|
||||||
|
write(d);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
namespace __SA_IS {
|
||||||
|
const int L_TYPE = 0;
|
||||||
|
const int S_TYPE = 1;
|
||||||
|
const int kMaxN = 3e5 + 10;
|
||||||
|
const int kMaxChar = 1e6;
|
||||||
|
int a[kMaxN * 2], sa[kMaxN * 2], typ[kMaxN * 2], c[kMaxChar * 2 + 5],
|
||||||
|
p[kMaxN * 2], sbuc[kMaxChar + 5], lbuc[kMaxChar + 5], name[kMaxN * 2];
|
||||||
|
|
||||||
|
inline int islms(int *typ, int i) { return !typ[i] && (i == 1 || typ[i - 1]); }
|
||||||
|
|
||||||
|
int cmp(int *s, int *typ, int p, int q) {
|
||||||
|
do {
|
||||||
|
if (s[p] != s[q]) return 1;
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
} while (!islms(typ, p) && !islms(typ, q));
|
||||||
|
return (!islms(typ, p) || !islms(typ, q) || s[p] != s[q]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void isort(int *s, int *sa, int *typ, int *c, int n, int m) {
|
||||||
|
int i;
|
||||||
|
for (lbuc[0] = sbuc[0] = c[0], i = 1; i <= m; i++) {
|
||||||
|
lbuc[i] = c[i - 1] + 1;
|
||||||
|
sbuc[i] = c[i];
|
||||||
|
}
|
||||||
|
for (i = 1; i <= n; i++)
|
||||||
|
if (sa[i] > 1 && typ[sa[i] - 1]) sa[lbuc[s[sa[i] - 1]]++] = sa[i] - 1;
|
||||||
|
for (i = n; i >= 1; i--)
|
||||||
|
if (sa[i] > 1 && !typ[sa[i] - 1]) sa[sbuc[s[sa[i] - 1]]--] = sa[i] - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_sa(int *s, int *sa, int *typ, int *c, int *p, int n, int m) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= m; i++) c[i] = 0;
|
||||||
|
for (i = 1; i <= n; i++) c[s[i]]++;
|
||||||
|
for (i = 1; i <= m; i++) c[i] += c[i - 1];
|
||||||
|
typ[n] = 0;
|
||||||
|
for (i = n - 1; i >= 1; i--)
|
||||||
|
if (s[i] < s[i + 1])
|
||||||
|
typ[i] = 0;
|
||||||
|
else if (s[i] > s[i + 1])
|
||||||
|
typ[i] = 1;
|
||||||
|
else
|
||||||
|
typ[i] = typ[i + 1];
|
||||||
|
int cnt = 0;
|
||||||
|
for (i = 1; i <= n; i++)
|
||||||
|
if (!typ[i] && (i == 1 || typ[i - 1])) p[++cnt] = i;
|
||||||
|
for (i = 1; i <= n; i++) sa[i] = 0;
|
||||||
|
for (i = 0; i <= m; i++) sbuc[i] = c[i];
|
||||||
|
for (i = 1; i <= cnt; i++) sa[sbuc[s[p[i]]]--] = p[i];
|
||||||
|
isort(s, sa, typ, c, n, m);
|
||||||
|
int last = 0, t = -1, x;
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
x = sa[i];
|
||||||
|
if (!typ[x] && (x == 1 || typ[x - 1])) {
|
||||||
|
if (!last || cmp(s, typ, x, last))
|
||||||
|
name[x] = ++t;
|
||||||
|
else
|
||||||
|
name[x] = t;
|
||||||
|
last = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 1; i <= cnt; i++) s[n + i] = name[p[i]];
|
||||||
|
if (t < cnt - 1)
|
||||||
|
build_sa(s + n, sa + n, typ + n, c + m + 1, p + n, cnt, t);
|
||||||
|
else
|
||||||
|
for (i = 1; i <= cnt; i++) sa[n + s[n + i] + 1] = i;
|
||||||
|
for (i = 0; i <= m; i++) sbuc[i] = c[i];
|
||||||
|
for (i = 1; i <= n; i++) sa[i] = 0;
|
||||||
|
for (i = cnt; i >= 1; i--) sa[sbuc[s[p[sa[n + i]]]]--] = p[sa[n + i]];
|
||||||
|
isort(s, sa, typ, c, n, m);
|
||||||
|
}
|
||||||
|
} // namespace __SA_IS
|
||||||
|
void SA_IS(int *s, int n, int *sa, int *rk) {
|
||||||
|
using namespace __SA_IS;
|
||||||
|
for (int i = 1; i <= n; i++) a[i] = s[i];
|
||||||
|
a[++n] = 0;
|
||||||
|
build_sa(a, sa, typ, c, p, n, kMaxChar);
|
||||||
|
n--;
|
||||||
|
for (int i = 1; i <= n; i++) sa[i] = sa[i + 1];
|
||||||
|
for (int i = 1; i <= n; i++) rk[sa[i]] = i;
|
||||||
|
}
|
||||||
|
void computeHeight(int *s, int n, int *sa, int *rk, int *height) {
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
if (rk[i] == 1) {
|
||||||
|
height[rk[i]] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (k > 0) { k--; }
|
||||||
|
int j = sa[rk[i] - 1];
|
||||||
|
while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) { k++; }
|
||||||
|
height[rk[i]] = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int kMaxN = 3e5 + 10;
|
||||||
|
int n;
|
||||||
|
int str[kMaxN << 2], sa[kMaxN << 2], rnk[kMaxN << 2], height[kMaxN], res[kMaxN];
|
||||||
|
const int kInf = 0x3f3f3f3f;
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
read(n);
|
||||||
|
for (int i = 1; i <= n; i++) read(str[i]);
|
||||||
|
SA_IS(str, n, sa, rnk);
|
||||||
|
computeHeight(str, n, sa, rnk, height);
|
||||||
|
vector<int> sa2, height2;
|
||||||
|
sa2.push_back(-1);
|
||||||
|
height2.push_back(-1);
|
||||||
|
sa2.push_back(sa[1]);
|
||||||
|
height2.push_back(0);
|
||||||
|
int current_shared_length = kInf;
|
||||||
|
for (int i = 2; i <= n; i++) {
|
||||||
|
current_shared_length = min(current_shared_length, height[i]);
|
||||||
|
if (sa[i] < sa2.back()) {
|
||||||
|
sa2.push_back(sa[i]);
|
||||||
|
height2.push_back(current_shared_length);
|
||||||
|
current_shared_length = kInf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<pair<int, int>> stk;
|
||||||
|
for (int i = sa2.size() - 1; i >= 1; i--) {
|
||||||
|
if (i == sa2.size() - 1) [[unlikely]] {
|
||||||
|
stk.push_back(make_pair(sa2[i], n + 1 - sa2[i]));
|
||||||
|
int L = 1;
|
||||||
|
if (i - 1 >= 1) L = n + 1 - sa2[i - 1] + 1;
|
||||||
|
for (int j = L; j <= n + 1 - sa2[i]; j++) res[j] = sa2[i];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
while (stk.size()) {
|
||||||
|
int h = height2[i + 1];
|
||||||
|
if (stk.back().second < h) break;
|
||||||
|
if (stk.size() >= 2 && (stk.end() - 2)->second >= h)
|
||||||
|
stk.pop_back();
|
||||||
|
else {
|
||||||
|
stk.back().second = h;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stk.push_back(make_pair(sa2[i], n + 1 - sa2[i]));
|
||||||
|
int L = 1;
|
||||||
|
if (i - 1 >= 1) L = n + 1 - sa2[i - 1] + 1;
|
||||||
|
for (int j = n + 1 - sa2[i], p = stk.size() - 1; j >= L; j--) {
|
||||||
|
while (p > 0 && stk[p - 1].second >= j) p--;
|
||||||
|
res[j] = stk[p].first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write(res[1]);
|
||||||
|
for (int i = 2; i <= n; i++) write(' ', res[i]);
|
||||||
|
write("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
61
ACMOJ-2133.cpp
Normal file
61
ACMOJ-2133.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
const int kMod = 19930726;
|
||||||
|
const int kMaxN = 1e6 + 10;
|
||||||
|
int n;
|
||||||
|
LL K;
|
||||||
|
char s[kMaxN];
|
||||||
|
int d1[kMaxN];
|
||||||
|
LL cnt[kMaxN];
|
||||||
|
LL qpow(int a, int b) {
|
||||||
|
LL res = 1;
|
||||||
|
while (b > 0) {
|
||||||
|
if (b & 1) res = (res * a) % kMod;
|
||||||
|
b >>= 1;
|
||||||
|
a = (a * (LL)a) % kMod;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d%lld", &n, &K);
|
||||||
|
scanf("%s", s);
|
||||||
|
for (int i = 0, l = 0, r = -1; i < n; i++) {
|
||||||
|
int k = (i > r) ? 1 : min(d1[l + r - i], r - i + 1);
|
||||||
|
while (0 <= i - k && i + k < n && s[i - k] == s[i + k]) { k++; }
|
||||||
|
d1[i] = k--;
|
||||||
|
if (i + k > r) {
|
||||||
|
l = i - k;
|
||||||
|
r = i + k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LL tot = 0;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
tot += d1[i];
|
||||||
|
cnt[d1[i]]++;
|
||||||
|
}
|
||||||
|
if (tot < K) {
|
||||||
|
printf("-1\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for(int i=n-1;i>=1;i--) cnt[i]+=cnt[i+1];
|
||||||
|
LL lft = K, res = 1;
|
||||||
|
for (int i = n; i >= 1; i--) {
|
||||||
|
if (cnt[i] > 0) {
|
||||||
|
if (cnt[i] < lft) {
|
||||||
|
res = (res * qpow(2 * i - 1, cnt[i])) % kMod;
|
||||||
|
lft -= cnt[i];
|
||||||
|
} else {
|
||||||
|
res = (res * qpow(2 * i - 1, lft)) % kMod;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("%lld\n", res);
|
||||||
|
return 0;
|
||||||
|
}
|
144
ACMOJ-2139.cpp
Normal file
144
ACMOJ-2139.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <unordered_map>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 1e5 + 10;
|
||||||
|
struct state {
|
||||||
|
int len, link;
|
||||||
|
unordered_map<char, int> next;
|
||||||
|
};
|
||||||
|
int n, m;
|
||||||
|
char str[kMaxN];
|
||||||
|
state st[kMaxN * 2];
|
||||||
|
int sz, last;
|
||||||
|
int prefix_node_id[kMaxN];
|
||||||
|
int root_of_node[kMaxN * 2];
|
||||||
|
struct SegNodeType {
|
||||||
|
int lc, rc, sum;
|
||||||
|
};
|
||||||
|
SegNodeType seg[kMaxN * 60];
|
||||||
|
int seg_node_tot = 0;
|
||||||
|
list<int> G[kMaxN * 2];
|
||||||
|
int max_depth, fast_jump[kMaxN * 2][20];
|
||||||
|
void sam_init() {
|
||||||
|
st[0].len = 0;
|
||||||
|
st[0].link = -1;
|
||||||
|
sz++;
|
||||||
|
last = 0;
|
||||||
|
}
|
||||||
|
void sam_extend(char c) {
|
||||||
|
int cur = sz++;
|
||||||
|
st[cur].len = st[last].len + 1;
|
||||||
|
int p = last;
|
||||||
|
while (p != -1 && !st[p].next.count(c)) {
|
||||||
|
st[p].next[c] = cur;
|
||||||
|
p = st[p].link;
|
||||||
|
}
|
||||||
|
if (p == -1) {
|
||||||
|
st[cur].link = 0;
|
||||||
|
} else {
|
||||||
|
int q = st[p].next[c];
|
||||||
|
if (st[p].len + 1 == st[q].len) {
|
||||||
|
st[cur].link = q;
|
||||||
|
} else {
|
||||||
|
int clone = sz++;
|
||||||
|
st[clone].len = st[p].len + 1;
|
||||||
|
st[clone].next = st[q].next;
|
||||||
|
st[clone].link = st[q].link;
|
||||||
|
while (p != -1 && st[p].next[c] == q) {
|
||||||
|
st[p].next[c] = clone;
|
||||||
|
p = st[p].link;
|
||||||
|
}
|
||||||
|
st[q].link = st[cur].link = clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last = cur;
|
||||||
|
}
|
||||||
|
void InsertBasicEndPos(int &rt, int L, int R, int pos) {
|
||||||
|
if (rt == 0) rt = ++seg_node_tot;
|
||||||
|
seg[rt].sum++;
|
||||||
|
if (L == R) return;
|
||||||
|
int M = (L + R) >> 1;
|
||||||
|
if (pos <= M)
|
||||||
|
InsertBasicEndPos(seg[rt].lc, L, M, pos);
|
||||||
|
else
|
||||||
|
InsertBasicEndPos(seg[rt].rc, M + 1, R, pos);
|
||||||
|
}
|
||||||
|
int Query(int rt, int L, int R, int ql, int qr) {
|
||||||
|
if (ql <= L && R <= qr) return seg[rt].sum;
|
||||||
|
int M = (L + R) >> 1;
|
||||||
|
int res = 0;
|
||||||
|
if (ql <= M) res += Query(seg[rt].lc, L, M, ql, qr);
|
||||||
|
if (qr >= M + 1) res += Query(seg[rt].rc, M + 1, R, ql, qr);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
int MergeSeg(int p, int q, int L, int R) {
|
||||||
|
if (p == 0 || q == 0) return p + q;
|
||||||
|
int cur = ++seg_node_tot;
|
||||||
|
seg[cur].sum = seg[p].sum + seg[q].sum;
|
||||||
|
if (L < R) {
|
||||||
|
int M = (L + R) >> 1;
|
||||||
|
seg[cur].lc = MergeSeg(seg[p].lc, seg[q].lc, L, M);
|
||||||
|
seg[cur].rc = MergeSeg(seg[p].rc, seg[q].rc, M + 1, R);
|
||||||
|
}
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
void Dfs(int nd) {
|
||||||
|
for (int p = 1; p <= max_depth; p++) {
|
||||||
|
if (fast_jump[nd][p - 1] == -1)
|
||||||
|
fast_jump[nd][p] = -1;
|
||||||
|
else
|
||||||
|
fast_jump[nd][p] = fast_jump[fast_jump[nd][p - 1]][p - 1];
|
||||||
|
}
|
||||||
|
for (auto v : G[nd]) {
|
||||||
|
fast_jump[v][0] = nd;
|
||||||
|
Dfs(v);
|
||||||
|
root_of_node[nd] = MergeSeg(root_of_node[nd], root_of_node[v], 1, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool IsValid(int len, int a, int b, int c, int d) {
|
||||||
|
int cur = prefix_node_id[c + len - 1];
|
||||||
|
for (int p = max_depth; p >= 0; p--) {
|
||||||
|
if (fast_jump[cur][p] != -1 && st[fast_jump[cur][p]].len >= len)
|
||||||
|
cur = fast_jump[cur][p];
|
||||||
|
}
|
||||||
|
return Query(root_of_node[cur], 1, n, a + len - 1, b) > 0;
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d%d", &n, &m);
|
||||||
|
scanf("%s", str + 1);
|
||||||
|
sam_init();
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
sam_extend(str[i]);
|
||||||
|
prefix_node_id[i] = last;
|
||||||
|
InsertBasicEndPos(root_of_node[last], 1, n, i);
|
||||||
|
}
|
||||||
|
for (int i = 1; i < sz; i++) G[st[i].link].push_back(i);
|
||||||
|
max_depth = log2(sz + 1) + 1;
|
||||||
|
memset(fast_jump, -1, sizeof(fast_jump));
|
||||||
|
Dfs(0);
|
||||||
|
while (m-- > 0) {
|
||||||
|
int a, b, c, d;
|
||||||
|
scanf("%d%d%d%d", &a, &b, &c, &d);
|
||||||
|
int L = 0, R = min(b - a + 1, d - c + 1), M, res = 0;
|
||||||
|
while (L <= R) {
|
||||||
|
M = (L + R) >> 1;
|
||||||
|
if (IsValid(M, a, b, c, d)) {
|
||||||
|
res = M;
|
||||||
|
L = M + 1;
|
||||||
|
} else
|
||||||
|
R = M - 1;
|
||||||
|
}
|
||||||
|
printf("%d\n", res);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
106
ACMOJ-2140.cpp
Normal file
106
ACMOJ-2140.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef unsigned long long ULL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 1e6 + 10;
|
||||||
|
char S[kMaxN], T[kMaxN];
|
||||||
|
struct Block {
|
||||||
|
enum TypeT { wild, exact } type;
|
||||||
|
int L, R;
|
||||||
|
};
|
||||||
|
Block S_block[kMaxN], T_block[kMaxN];
|
||||||
|
int S_block_cnt, T_block_cnt;
|
||||||
|
int len_S, len_T;
|
||||||
|
ULL S_hash_data[kMaxN], T_hash_data[kMaxN], ksm[kMaxN];
|
||||||
|
void Process(char *S, int len_S, Block *blocks, int &block_cnt) {
|
||||||
|
int current_left_bound = 0;
|
||||||
|
Block::TypeT current_type =
|
||||||
|
(S[0] == '?' ? Block::TypeT::wild : Block::TypeT::exact);
|
||||||
|
for (int i = 1; i < len_S; i++) {
|
||||||
|
Block::TypeT this_type =
|
||||||
|
(S[i] == '?' ? Block::TypeT::wild : Block::TypeT::exact);
|
||||||
|
if (this_type == current_type) continue;
|
||||||
|
blocks[block_cnt++] = Block{current_type, current_left_bound, i - 1};
|
||||||
|
current_type = this_type;
|
||||||
|
current_left_bound = i;
|
||||||
|
}
|
||||||
|
blocks[block_cnt++] = Block{current_type, current_left_bound, len_S - 1};
|
||||||
|
}
|
||||||
|
void PrepareHash(char *src, int len, ULL *dst) {
|
||||||
|
static const ULL mul = 131;
|
||||||
|
dst[0] = src[0] - 'a' + 1;
|
||||||
|
for (int i = 1; i < len; i++) {
|
||||||
|
dst[i] = dst[i - 1] * mul;
|
||||||
|
dst[i] += src[i] - 'a' + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ULL GetHsh(char *str, ULL *dat, int L, int R) {
|
||||||
|
ULL res = 0;
|
||||||
|
if (L > 0)
|
||||||
|
res = dat[R] - dat[L - 1] * ksm[R - L + 1];
|
||||||
|
else
|
||||||
|
res = dat[R];
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
bool Matched(int pos) {
|
||||||
|
int current_T_iterator = 0;
|
||||||
|
static int stored_begin_S_iterator = 0;
|
||||||
|
int current_S_iterator = stored_begin_S_iterator;
|
||||||
|
Block current_S_block = S_block[0];
|
||||||
|
Block current_T_block = T_block[0];
|
||||||
|
while (S_block[current_S_iterator].R < pos) current_S_iterator++;
|
||||||
|
stored_begin_S_iterator = current_S_iterator;
|
||||||
|
current_S_block = S_block[current_S_iterator];
|
||||||
|
assert(current_S_block.L <= pos);
|
||||||
|
assert(current_S_block.R >= pos);
|
||||||
|
current_S_block.L = pos;
|
||||||
|
while (true) {
|
||||||
|
int current_compare_length = min(current_S_block.R - current_S_block.L + 1,
|
||||||
|
current_T_block.R - current_T_block.L + 1);
|
||||||
|
if (current_S_block.type == Block::TypeT::exact &&
|
||||||
|
current_T_block.type == Block::TypeT::exact) {
|
||||||
|
if (GetHsh(S, S_hash_data, current_S_block.L,
|
||||||
|
current_S_block.L + current_compare_length - 1) !=
|
||||||
|
GetHsh(T, T_hash_data, current_T_block.L,
|
||||||
|
current_T_block.L + current_compare_length - 1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (current_compare_length == current_T_block.R - current_T_block.L + 1) {
|
||||||
|
if (current_T_iterator == T_block_cnt - 1) return true;
|
||||||
|
current_T_iterator++;
|
||||||
|
current_T_block = T_block[current_T_iterator];
|
||||||
|
} else
|
||||||
|
current_T_block.L += current_compare_length;
|
||||||
|
if (current_compare_length == current_S_block.R - current_S_block.L + 1) {
|
||||||
|
current_S_iterator++;
|
||||||
|
current_S_block = S_block[current_S_iterator];
|
||||||
|
} else
|
||||||
|
current_S_block.L += current_compare_length;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%s%s", S, T);
|
||||||
|
len_S = strlen(S);
|
||||||
|
len_T = strlen(T);
|
||||||
|
Process(S, len_S, S_block, S_block_cnt);
|
||||||
|
Process(T, len_T, T_block, T_block_cnt);
|
||||||
|
PrepareHash(S, len_S, S_hash_data);
|
||||||
|
PrepareHash(T, len_T, T_hash_data);
|
||||||
|
ksm[0] = 1;
|
||||||
|
static const ULL mul = 131;
|
||||||
|
for (int i = 1; i < kMaxN; i++) ksm[i] = ksm[i - 1] * mul;
|
||||||
|
for (int pos = 0; pos < len_S - len_T + 1; pos++) {
|
||||||
|
if (Matched(pos)) printf("%d\n", pos);
|
||||||
|
// fprintf(stderr, "pos=%d\n", pos);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
66
ACMOJ-2147.cpp
Normal file
66
ACMOJ-2147.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 510;
|
||||||
|
const int kMaxT = 4e6 + 100 + 10;
|
||||||
|
int n, m;
|
||||||
|
int t[kMaxN];
|
||||||
|
int bucket[kMaxT], bucket_tot[kMaxT], max_t;
|
||||||
|
LL f[kMaxT], bucket_t_sum[kMaxT];
|
||||||
|
int Q[kMaxT], QL, QR;
|
||||||
|
inline LL GetY(int id) { return f[id] + bucket_t_sum[id]; }
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d%d", &n, &m);
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
scanf("%d", &t[i]);
|
||||||
|
bucket[t[i]]++;
|
||||||
|
max_t = t[i] > max_t ? t[i] : max_t;
|
||||||
|
}
|
||||||
|
bucket_tot[0] = bucket[0];
|
||||||
|
for (int i = 1; i <= max_t + m - 1; i++) {
|
||||||
|
bucket_tot[i] = bucket_tot[i - 1] + bucket[i];
|
||||||
|
bucket_t_sum[i] = bucket_t_sum[i - 1] + i * (LL)bucket[i];
|
||||||
|
}
|
||||||
|
QL = 0;
|
||||||
|
QR = -1;
|
||||||
|
int pend_cur = 0;
|
||||||
|
for (int i = 0; i <= max_t + m - 1; i++) {
|
||||||
|
f[i] = bucket_tot[i] * (LL)i - bucket_t_sum[i];
|
||||||
|
// for (int j = 0; j + m <= i; j++) {
|
||||||
|
// f[i] = min(f[i], f[j] + (bucket_tot[i] - bucket_tot[j]) * (LL)i -
|
||||||
|
// bucket_t_sum[i] + bucket_t_sum[j]);
|
||||||
|
// // f[j] + bucket_t_sum[j] =i*bucket_tot[j]+ f[i] - bucket_tot[i]*i +
|
||||||
|
// // bucket_t_sum[i]
|
||||||
|
// }
|
||||||
|
while (pend_cur + m <= i) {
|
||||||
|
while (QR - QL + 1 >= 2 &&
|
||||||
|
(bucket_tot[pend_cur] - bucket_tot[Q[QR - 1]]) *
|
||||||
|
(GetY(Q[QR]) - GetY(Q[QR - 1])) -
|
||||||
|
(GetY(pend_cur) - GetY(Q[QR - 1])) *
|
||||||
|
(bucket_tot[Q[QR]] - bucket_tot[Q[QR - 1]]) >=
|
||||||
|
0)
|
||||||
|
QR--;
|
||||||
|
Q[++QR] = pend_cur;
|
||||||
|
pend_cur++;
|
||||||
|
}
|
||||||
|
while (QR - QL + 1 >= 2 &&
|
||||||
|
GetY(Q[QL + 1]) - GetY(Q[QL]) <=
|
||||||
|
i * (LL)(bucket_tot[Q[QL + 1]] - bucket_tot[Q[QL]]))
|
||||||
|
QL++;
|
||||||
|
if (QL <= QR)
|
||||||
|
f[i] = min(f[i], f[Q[QL]] + (bucket_tot[i] - bucket_tot[Q[QL]]) * (LL)i -
|
||||||
|
bucket_t_sum[i] + bucket_t_sum[Q[QL]]);
|
||||||
|
// printf("f(%d)=%lld\n", i, f[i]);
|
||||||
|
}
|
||||||
|
LL res = 0x3f3f3f3f3f3f3f3f;
|
||||||
|
for (int i = max_t; i <= max_t + m - 1; i++) res = min(res, f[i]);
|
||||||
|
printf("%lld\n", res);
|
||||||
|
return 0;
|
||||||
|
}
|
107
ACMOJ-2148.cpp
Normal file
107
ACMOJ-2148.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 1e5 + 10;
|
||||||
|
int N, S;
|
||||||
|
LDB A[kMaxN], B[kMaxN], R[kMaxN];
|
||||||
|
struct NodeType {
|
||||||
|
int rawid;
|
||||||
|
LDB a, b, r, f;
|
||||||
|
};
|
||||||
|
NodeType nodes[kMaxN];
|
||||||
|
inline LDB GetX(const NodeType &node) {
|
||||||
|
return node.f * node.r / (node.a * node.r + node.b);
|
||||||
|
}
|
||||||
|
inline LDB GetY(const NodeType &node) {
|
||||||
|
return node.f / (node.a * node.r + node.b);
|
||||||
|
}
|
||||||
|
bool CmpX(const NodeType &na, const NodeType &nb) {
|
||||||
|
return GetX(na) < GetX(nb);
|
||||||
|
}
|
||||||
|
bool CmpId(const NodeType &na, const NodeType &nb) {
|
||||||
|
return na.rawid < nb.rawid;
|
||||||
|
}
|
||||||
|
bool CmpK(const NodeType &na, const NodeType &nb) {
|
||||||
|
return -na.a / na.b > -nb.a / nb.b;
|
||||||
|
}
|
||||||
|
int Q[kMaxN], QL, QR;
|
||||||
|
typedef bool (*CmpType)(const NodeType &, const NodeType &);
|
||||||
|
void MergeSort(NodeType *beg, NodeType *end, CmpType cmp) {
|
||||||
|
if (end - beg <= 1) return;
|
||||||
|
size_t len = end - beg;
|
||||||
|
NodeType *mid = beg + (len >> 1);
|
||||||
|
MergeSort(beg, mid, cmp);
|
||||||
|
MergeSort(mid, end, cmp);
|
||||||
|
NodeType *tmp = new NodeType[len];
|
||||||
|
NodeType *cur_tmp = tmp, *cur_L = beg, *cur_R = mid;
|
||||||
|
while ((cur_L < mid) && (cur_R < end)) {
|
||||||
|
if (cmp(*cur_L, *cur_R))
|
||||||
|
*(cur_tmp++) = *(cur_L++);
|
||||||
|
else
|
||||||
|
*(cur_tmp++) = *(cur_R++);
|
||||||
|
}
|
||||||
|
while (cur_L < mid) *(cur_tmp++) = *(cur_L++);
|
||||||
|
while (cur_R < end) *(cur_tmp++) = *(cur_R++);
|
||||||
|
cur_tmp = tmp;
|
||||||
|
NodeType *cur_dst = beg;
|
||||||
|
while (cur_dst < end) *(cur_dst++) = *(cur_tmp++);
|
||||||
|
delete[] tmp;
|
||||||
|
}
|
||||||
|
void CDQ(int L, int R) {
|
||||||
|
if (L == R) return;
|
||||||
|
int M = (L + R) >> 1;
|
||||||
|
CDQ(L, M);
|
||||||
|
MergeSort(nodes + L, nodes + M + 1, CmpX);
|
||||||
|
MergeSort(nodes + M + 1, nodes + R + 1, CmpK);
|
||||||
|
Q[QL = QR = 0] = L;
|
||||||
|
for (int i = L + 1; i <= M; i++) {
|
||||||
|
while (QR - QL + 1 >= 2 &&
|
||||||
|
(GetX(nodes[Q[QR]]) - GetX(nodes[Q[QR - 1]])) *
|
||||||
|
(GetY(nodes[i]) - GetY(nodes[Q[QR - 1]])) -
|
||||||
|
(GetY(nodes[Q[QR]]) - GetY(nodes[Q[QR - 1]])) *
|
||||||
|
(GetX(nodes[i]) - GetX(nodes[Q[QR - 1]])) >=
|
||||||
|
0)
|
||||||
|
QR--;
|
||||||
|
Q[++QR] = i;
|
||||||
|
}
|
||||||
|
LDB base = 0;
|
||||||
|
for (int i = L; i <= M; i++) base = max(base, nodes[i].f);
|
||||||
|
for (int i = M + 1; i <= R; i++) {
|
||||||
|
while (QR - QL + 1 >= 2 &&
|
||||||
|
(GetY(nodes[Q[QL + 1]]) - GetY(nodes[Q[QL]])) /
|
||||||
|
(GetX(nodes[Q[QL + 1]]) - GetX(nodes[Q[QL]])) >=
|
||||||
|
-nodes[i].a / nodes[i].b)
|
||||||
|
QL++;
|
||||||
|
nodes[i].f = max(nodes[i].f, base);
|
||||||
|
nodes[i].f = max(nodes[i].f, nodes[i].a * GetX(nodes[Q[QL]]) +
|
||||||
|
nodes[i].b * GetY(nodes[Q[QL]]));
|
||||||
|
}
|
||||||
|
MergeSort(nodes + M + 1, nodes + R + 1, CmpId);
|
||||||
|
CDQ(M + 1, R);
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d%d", &N, &S);
|
||||||
|
for (int i = 1; i <= N; i++) {
|
||||||
|
scanf("%Lf%Lf%Lf", &A[i], &B[i], &R[i]);
|
||||||
|
nodes[i].rawid = i;
|
||||||
|
nodes[i].a = A[i];
|
||||||
|
nodes[i].b = B[i];
|
||||||
|
nodes[i].r = R[i];
|
||||||
|
}
|
||||||
|
nodes[1].f = S;
|
||||||
|
CDQ(1, N);
|
||||||
|
// for (int i = 1; i <= N; i++)
|
||||||
|
// printf("f(%d)=%.3Lf\n", nodes[i].rawid, nodes[i].f);
|
||||||
|
for (int i = 1; i <= N; i++)
|
||||||
|
if (nodes[i].rawid == N) {
|
||||||
|
printf("%.3Lf\n", nodes[i].f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
36
ACMOJ-2163.cpp
Normal file
36
ACMOJ-2163.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 1e5 + 10;
|
||||||
|
int n, key[kMaxN], w[kMaxN];
|
||||||
|
int stk[kMaxN], ls[kMaxN], rs[kMaxN];
|
||||||
|
void dfs(int rt) {
|
||||||
|
printf("%d ", rt);
|
||||||
|
if (ls[rt]) dfs(ls[rt]);
|
||||||
|
if (rs[rt]) dfs(rs[rt]);
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d", &n);
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
scanf("%d", &key[i]);
|
||||||
|
w[key[i]] = i;
|
||||||
|
}
|
||||||
|
int top = 0;
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
int k = top;
|
||||||
|
while (k > 0 && w[stk[k]] > w[i]) k--;
|
||||||
|
if (k) rs[stk[k]] = i; // rs代表笛卡尔树每个节点的右儿子
|
||||||
|
if (k < top) ls[i] = stk[k + 1]; // ls代表笛卡尔树每个节点的左儿子
|
||||||
|
stk[++k] = i;
|
||||||
|
top = k;
|
||||||
|
}
|
||||||
|
dfs(stk[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
59
ACMOJ-2165.cpp
Normal file
59
ACMOJ-2165.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 1e4 + 10;
|
||||||
|
const LDB kEps = 1e-4;
|
||||||
|
int n, a, b;
|
||||||
|
LDB p[kMaxN], q[kMaxN];
|
||||||
|
LDB calcxy(LDB x, LDB y) {
|
||||||
|
LDB tot = a * x + b * y;
|
||||||
|
for (int i = 1; i <= n; i++)
|
||||||
|
tot += max({LDB(0), p[i] - x, q[i] - y, p[i] + q[i] - p[i] * q[i] - x - y});
|
||||||
|
return tot;
|
||||||
|
}
|
||||||
|
LDB calcx(LDB x) {
|
||||||
|
LDB res=0;
|
||||||
|
LDB left_bound = -1e4, right_bound = 1e4;
|
||||||
|
while (right_bound - left_bound > kEps) {
|
||||||
|
LDB l_mid = (left_bound + left_bound + right_bound) / 3;
|
||||||
|
LDB r_mid = (left_bound + right_bound + right_bound) / 3;
|
||||||
|
LDB l_res = calcxy(x, l_mid);
|
||||||
|
LDB r_res = calcxy(x, r_mid);
|
||||||
|
res = (l_res + r_res) / 2;
|
||||||
|
if (l_res > r_res)
|
||||||
|
left_bound = l_mid;
|
||||||
|
else
|
||||||
|
right_bound = r_mid;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
LDB calc() {
|
||||||
|
LDB res = 0;
|
||||||
|
LDB left_bound = -1e4, right_bound = 1e4;
|
||||||
|
while (right_bound - left_bound > kEps) {
|
||||||
|
LDB l_mid = (left_bound + left_bound + right_bound) / 3;
|
||||||
|
LDB r_mid = (left_bound + right_bound + right_bound) / 3;
|
||||||
|
LDB l_res = calcx(l_mid);
|
||||||
|
LDB r_res = calcx(r_mid);
|
||||||
|
res = (l_res + r_res) / 2;
|
||||||
|
if (l_res > r_res)
|
||||||
|
left_bound = l_mid;
|
||||||
|
else
|
||||||
|
right_bound = r_mid;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d%d%d", &n, &a, &b);
|
||||||
|
for (int i = 1; i <= n; i++) scanf("%Lf", &p[i]);
|
||||||
|
for (int i = 1; i <= n; i++) scanf("%Lf", &q[i]);
|
||||||
|
printf("%.2Lf\n", calc());
|
||||||
|
return 0;
|
||||||
|
}
|
92
ACMOJ-2178.cpp
Normal file
92
ACMOJ-2178.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 310;
|
||||||
|
char s[kMaxN];
|
||||||
|
int N, M;
|
||||||
|
int Calc1(int st) {
|
||||||
|
int target[20] = {0};
|
||||||
|
for (int i = 0; i < M; i++) target[i] = (st >> i) & 1;
|
||||||
|
int cost[kMaxN][2] = {0};
|
||||||
|
int bucket_tot = N / M;
|
||||||
|
int left = N % M;
|
||||||
|
int initial_cost = 0;
|
||||||
|
for (int i = 0; i < left; i++)
|
||||||
|
initial_cost += s[bucket_tot * M + i] != target[i] ? 1 : 0;
|
||||||
|
for (int i = 0; i < bucket_tot; i++) {
|
||||||
|
for (int j = 0; j < M; j++) {
|
||||||
|
if (s[i * M + j] == target[j])
|
||||||
|
cost[i][1]++;
|
||||||
|
else
|
||||||
|
cost[i][0]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int dp[kMaxN][2];
|
||||||
|
memset(dp, 0x3f, sizeof(dp));
|
||||||
|
dp[bucket_tot][0] = initial_cost;
|
||||||
|
for (int i = bucket_tot - 1; i >= 0; i--) {
|
||||||
|
dp[i][0] = min(dp[i + 1][0] + cost[i][0], dp[i + 1][1] + cost[i][0] + 1);
|
||||||
|
dp[i][1] = min(dp[i + 1][0] + cost[i][1] + 1, dp[i + 1][1] + cost[i][1]);
|
||||||
|
}
|
||||||
|
return min(dp[0][0], dp[0][1]);
|
||||||
|
}
|
||||||
|
void Case1() {
|
||||||
|
int res = 0x3f3f3f3f;
|
||||||
|
for (int i = 0; i < N; i++) s[i] = s[i] - '0';
|
||||||
|
for (int st = 0; st < (1 << M); st++) res = min(res, Calc1(st));
|
||||||
|
printf("%d\n", res);
|
||||||
|
}
|
||||||
|
int Calc2(int st) {
|
||||||
|
int bucket_tot = N / M;
|
||||||
|
int cur_status = 0, status = 0;
|
||||||
|
int tot = 0;
|
||||||
|
for (int i = bucket_tot - 1; i >= 0; i--) {
|
||||||
|
int cur = (st >> i) & 1;
|
||||||
|
tot += cur;
|
||||||
|
cur_status ^= cur;
|
||||||
|
status <<= 1;
|
||||||
|
status |= cur_status;
|
||||||
|
}
|
||||||
|
int S[kMaxN];
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
S[i] = s[i] - '0';
|
||||||
|
int block_id = i / M;
|
||||||
|
int hat = (status >> block_id) & 1;
|
||||||
|
S[i] ^= hat;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < M; i++) {
|
||||||
|
int cnt_one = 0;
|
||||||
|
int cnt_zero = 0;
|
||||||
|
for (int j = i; j < N; j += M) {
|
||||||
|
if (S[j] == 1)
|
||||||
|
cnt_one++;
|
||||||
|
else
|
||||||
|
cnt_zero++;
|
||||||
|
}
|
||||||
|
tot += min(cnt_one, cnt_zero);
|
||||||
|
}
|
||||||
|
return tot;
|
||||||
|
}
|
||||||
|
void Case2() {
|
||||||
|
int bucket_tot = N / M;
|
||||||
|
int res = 0x3f3f3f3f;
|
||||||
|
for (int st = 0; st < (1 << bucket_tot); st++) res = min(res, Calc2(st));
|
||||||
|
printf("%d\n", res);
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%s%d", s, &M);
|
||||||
|
N = strlen(s);
|
||||||
|
if (M <= sqrt(N))
|
||||||
|
Case1();
|
||||||
|
else
|
||||||
|
Case2();
|
||||||
|
return 0;
|
||||||
|
}
|
78
ACMOJ-2179.cpp
Normal file
78
ACMOJ-2179.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
using namespace std;
|
||||||
|
template <typename T>
|
||||||
|
inline void read(T &t) {
|
||||||
|
t = 0;
|
||||||
|
int ch, f = false;
|
||||||
|
while (ch = getchar(), !((ch >= '0' && ch <= '9') || ch == '-'))
|
||||||
|
;
|
||||||
|
if (ch == '-') f = true, ch = getchar();
|
||||||
|
t = ch ^ 48;
|
||||||
|
while (ch = getchar(), ch >= '0' && ch <= '9') t = t * 10 + (ch ^ 48);
|
||||||
|
if (f) t = -t;
|
||||||
|
}
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
inline void read(T &t, Args &...args) {
|
||||||
|
read(t);
|
||||||
|
read(args...);
|
||||||
|
}
|
||||||
|
const int maxn = 500005;
|
||||||
|
const int maxm = 200005;
|
||||||
|
struct Query {
|
||||||
|
int l, r, id;
|
||||||
|
};
|
||||||
|
Query q[maxm];
|
||||||
|
int n, m, cnt[1000001], tot, a[maxn], res[maxm], bid[maxn];
|
||||||
|
inline bool cmp(const Query &a, const Query &b) {
|
||||||
|
return bid[a.l] != bid[b.l] ? bid[a.l] < bid[b.l]
|
||||||
|
: ((bid[a.l] & 1) ? a.r < b.r : a.r > b.r);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
void MergeSort(T *beg, T *end, bool (*cmp)(const T &, const T &)) {
|
||||||
|
if (end - beg <= 1) return;
|
||||||
|
size_t len = end - beg;
|
||||||
|
T *mid = beg + (len >> 1);
|
||||||
|
MergeSort(beg, mid, cmp);
|
||||||
|
MergeSort(mid, end, cmp);
|
||||||
|
T *tmp = new T[len];
|
||||||
|
T *cur_tmp = tmp, *cur_L = beg, *cur_R = mid;
|
||||||
|
while ((cur_L < mid) && (cur_R < end)) {
|
||||||
|
if (cmp(*cur_L, *cur_R))
|
||||||
|
*(cur_tmp++) = *(cur_L++);
|
||||||
|
else
|
||||||
|
*(cur_tmp++) = *(cur_R++);
|
||||||
|
}
|
||||||
|
while (cur_L < mid) *(cur_tmp++) = *(cur_L++);
|
||||||
|
while (cur_R < end) *(cur_tmp++) = *(cur_R++);
|
||||||
|
cur_tmp = tmp;
|
||||||
|
T *cur_dst = beg;
|
||||||
|
while (cur_dst < end) *(cur_dst++) = *(cur_tmp++);
|
||||||
|
delete[] tmp;
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
read(n);
|
||||||
|
for (int i = 1; i <= n; i++) read(a[i]);
|
||||||
|
read(m);
|
||||||
|
for (int i = 1; i <= m; i++) read(q[i].l, q[i].r), q[i].id = i;
|
||||||
|
int blo = sqrt(n);
|
||||||
|
for (int i = 1; i <= n; i++) bid[i] = (i - 1) / blo + 1;
|
||||||
|
MergeSort(q + 1, q + 1 + m, cmp);
|
||||||
|
int l = q[1].l, r = q[1].r;
|
||||||
|
for (int i = l; i <= r; i++) tot += (++cnt[a[i]] == 1);
|
||||||
|
res[q[1].id] = tot;
|
||||||
|
for (int i = 2; i <= m; i++) {
|
||||||
|
Query &Q = q[i];
|
||||||
|
while (l < Q.l) tot -= (--cnt[a[l++]] == 0);
|
||||||
|
while (l > Q.l) tot += (++cnt[a[--l]] == 1);
|
||||||
|
while (r > Q.r) tot -= (--cnt[a[r--]] == 0);
|
||||||
|
while (r < Q.r) tot += (++cnt[a[++r]] == 1);
|
||||||
|
res[Q.id] = tot;
|
||||||
|
}
|
||||||
|
for (int i = 1; i <= m; i++) printf("%d\n", res[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
41
ACMOJ-2180.cpp
Normal file
41
ACMOJ-2180.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
typedef long long LL;
|
||||||
|
typedef long double LDB;
|
||||||
|
const int kMaxN = 1e5 + 10;
|
||||||
|
int n, m, a[kMaxN];
|
||||||
|
LL small_bucket[400][400];
|
||||||
|
int main() {
|
||||||
|
#ifdef local
|
||||||
|
freopen("pro.in", "r", stdin);
|
||||||
|
#endif
|
||||||
|
scanf("%d%d", &n, &m);
|
||||||
|
for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); }
|
||||||
|
int boundary = sqrt(n);
|
||||||
|
assert(boundary < 400);
|
||||||
|
for (int i = 1; i <= n; i++)
|
||||||
|
for (int j = 1; j <= boundary; j++) small_bucket[j][i % j] += a[i];
|
||||||
|
while (m-- > 0) {
|
||||||
|
int opt, x, y;
|
||||||
|
scanf("%d%d%d", &opt, &x, &y);
|
||||||
|
if (opt == 1) {
|
||||||
|
if (x <= boundary) {
|
||||||
|
printf("%lld\n", small_bucket[x][y % x]);
|
||||||
|
} else {
|
||||||
|
LL res = 0;
|
||||||
|
for (int i = y; i <= n; i += x) res += a[i];
|
||||||
|
printf("%lld\n", res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 1; i <= boundary; i++) small_bucket[i][x % i] -= a[x];
|
||||||
|
a[x] = y;
|
||||||
|
for (int i = 1; i <= boundary; i++) small_bucket[i][x % i] += a[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
1039
ACMOJ-2181.cpp
Normal file
1039
ACMOJ-2181.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user