This commit is contained in:
2024-04-18 18:38:55 +08:00
parent bfcbb1996a
commit 4f8f929242
20 changed files with 3408 additions and 0 deletions

818
ACMOJ-1335.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff