跑得还是蛮快的,https://www.luogu.com.cn/record/226412111,出现了死循环(一个点)和 WA 一堆点。
感觉是边界问题(大分块边界我就没打对过),求调。
悬三个小号的关注。
504 行开始是代码,前面的东西是 debug 库和快读快写。大概不是快读快写的问题。
#include <bits/stdc++.h>
using namespace std;
#define variable_name(x) #x
#define vdebug(x) variable_name(x) << " = " << x
#define pdebug(x) "*" << variable_name(x) << " = " << *(x)
#define all(x) (x).begin(), (x).end()
#define adebug(a, b, c) #a << "[" << (b) << "..." << (c) << "] = " << vector<typename decay<decltype(*((a) + (b)))>::type>((a) + (b), (a) + (c) + 1)
namespace quick_io {
#if defined(__GNUC__) && defined(__SIZEOF_INT128__)
#ifndef quick_io_can_use_int128
#define quick_io_can_use_int128
#define mark_can_use_in_quick_io
#endif
#endif
#ifdef quick_io_can_use_int128
#define quick_io_int_length_limit 128
#define quick_io_int_radix_type size_t
#define quick_io_length_type size_t
bool is_digit[128];
quick_io_int_radix_type cur_int_radix = 0;
char __quick_io_d2c(size_t a) {
if (a <= 9) {
return '0' + a;
} else if (a <= 35) {
return 'A' + a - 10;
} else {
return 'a' + a - 36;
}
}
size_t __quick_io_c2d(char a) {
if (a >= '0' && a <= '9') {
return a - '0';
} else if (a >= 'A' && a <= 'Z') {
return a - 'A' + 10;
} else /*if (a >= 'a' && a <= 'z')*/ {
return a - 'a' + 36;
}
}
struct quick_io_change_int_radix {
quick_io_change_int_radix(quick_io_int_radix_type new_int_radix) {
if (cur_int_radix == new_int_radix) return;
cur_int_radix = new_int_radix;
memset(is_digit, 0, sizeof(is_digit));
for (size_t i = 0; i < new_int_radix; i++) {
is_digit[size_t(__quick_io_d2c(i))] = true;
}
}
} set_radix(10);
// Weak robustness, maybe can't be correct if the input format changes
// Very slow functions
ostream &operator<<(ostream &A, __int128 b) {
char a[128], k = 0;
memset(a, 0, sizeof(a));
quick_io_length_type pos = 0;
unsigned __int128 b_ = b;
if (b < 0) k = -1, b_ = -b;
while (b_) {
a[pos++] = __quick_io_d2c(b_ % cur_int_radix);
b_ /= cur_int_radix;
}
if (!~k) {
a[pos++] = '-';
}
if (!pos) {
a[pos++] = '0';
}
reverse(a, a + pos);
return A << a;
}
istream &operator>>(istream &A, __int128 &b) {
int k = 1;
char c = A.get();
b = 0;
while (c != '-' && c != '+' && !is_digit[size_t(c)]) {
c = A.get();
}
if (c == '-') {
k = -1;
c = A.get();
} else if (c == '+') {
c = A.get();
}
while (is_digit[size_t(c)]) {
b = b * cur_int_radix + __quick_io_c2d(c);
c = A.get();
}
if (!~k) b = -b;
A.unget();
return A;
}
ostream &operator<<(ostream &A, unsigned __int128 b) {
char a[128];
memset(a, 0, sizeof(a));
quick_io_length_type pos = 0;
while (b) {
a[pos++] = __quick_io_d2c(b % cur_int_radix);
b /= cur_int_radix;
}
if (!pos) {
a[pos++] = '0';
}
reverse(a, a + pos);
return A << a;
}
istream &operator>>(istream &A, unsigned __int128 &b) {
char c = A.get();
b = 0;
while (!is_digit[size_t(c)]) {
c = A.get();
}
while (is_digit[size_t(c)]) {
b = b * cur_int_radix + __quick_io_c2d(c);
c = A.get();
}
A.unget();
return A;
}
#ifdef mark_can_use_in_quick_io
#undef quick_io_can_use_int128
#undef mark_can_use_in_quick_io
#endif
#endif
template<typename T>
ostream &operator<<(ostream &A, const vector<T> &b);
template<typename T>
ostream &operator<<(ostream &A, const deque<T> &b);
template<typename T1, typename T2>
ostream &operator<<(ostream &A, const pair<T1, T2> &b);
template<typename T>
ostream &operator<<(ostream &A, const set<T> &b);
template<typename T>
ostream &operator<<(ostream &A, const multiset<T> &b);
template<typename T, typename T2>
ostream &operator<<(ostream &A, const map<T, T2> &b);
template<typename T, typename T2>
ostream &operator<<(ostream &A, const multimap<T, T2> &b);
template<typename T>
ostream &operator<<(ostream &A, const unordered_set<T> &b);
template<typename T>
ostream &operator<<(ostream &A, const unordered_multiset<T> &b);
template<typename T, typename T2>
ostream &operator<<(ostream &A, const unordered_map<T, T2> &b);
template<typename T, typename T2>
ostream &operator<<(ostream &A, const unordered_multimap<T, T2> &b);
template<typename T>
ostream &operator<<(ostream &A, const vector<T> &b) {
A << "[";
for (size_t i = 0; i + 1 < b.size(); i++) {
A << b[i] << ",";
}
if (b.size()) {
A << b[b.size() - 1];
}
A << "]";
return A;
}
template<typename T>
ostream &operator<<(ostream &A, const deque<T> &b) {
A << "[";
for (size_t i = 0; i + 1 < b.size(); i++) {
A << b[i] << ",";
}
if (b.size()) {
A << b[b.size() - 1];
}
A << "]";
return A;
}
template<typename T1, typename T2>
ostream &operator<<(ostream &A, const pair<T1, T2> &b) {
return A << '(' << b.first << ',' << b.second << ')';
}
template<typename T>
ostream &operator<<(ostream &A, const set<T> &b) {
typename set<T>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T>
ostream &operator<<(ostream &A, const multiset<T> &b) {
typename multiset<T>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T, typename T2>
ostream &operator<<(ostream &A, const map<T, T2> &b) {
typename map<T, T2>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T, typename T2>
ostream &operator<<(ostream &A, const multimap<T, T2> &b) {
typename multimap<T, T2>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T>
ostream &operator<<(ostream &A, const unordered_set<T> &b) {
typename unordered_set<T>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T>
ostream &operator<<(ostream &A, const unordered_multiset<T> &b) {
typename unordered_multiset<T>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T, typename T2>
ostream &operator<<(ostream &A, const unordered_multimap<T, T2> &b) {
typename unordered_multimap<T, T2>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T, typename T2>
ostream &operator<<(ostream &A, const unordered_map<T, T2> &b) {
typename unordered_map<T, T2>::const_iterator i = b.begin(), e = b.end();
A << "{";
while (i != e) {
A << *i;
i++;
if (i != e) {
A << ",";
}
}
return A << "}";
}
template<typename T1, typename T2>
istream &operator>>(istream &A, pair<T1, T2> &b) {
return A >> b.first >> b.second;
}
template<typename T>
void print_array(T b, T e, string s = " ") {
while (b != e) {
cout << *b;
b++;
if (b != e) {
cout << s;
}
}
}
template<typename T>
void auto_print(T &b, size_t n, string s = " ") {
for (size_t i = 1; i < n; i++) {
cout << b[i] << s;
}
cout << b[n];
}
template<typename T>
void auto_print(T &b, string s = " ") {
for (auto i : b) {
cout << i << s;
}
}
template<typename T>
void print_n(T b, size_t n, string s = " ") {
if (n == 0) return;
cout << *b;
for (size_t i = 1; i < n; i++) {
b++;
cout << s << *b;
}
}
template<typename T>
void read_array(T b, T e) {
while (b != e) {
cin >> *b;
b++;
}
}
template<typename T>
void auto_read(T &b, size_t n) {
for (size_t i = 1; i <= n; i++) {
cin >> b[i];
}
}
template<typename T>
void read_n(T b, size_t n) { // untested
cin >> *b;
for (size_t i = 1; i < n; i++) {
b++;
cin >> *b;
}
}
template <typename T>
string to_string(const T& value) {
ostringstream oss;
oss << value;
return oss.str();
}
template <typename Array>
string array_debug_impl(const Array& a) {
return "";
}
template <typename Array, typename First, typename... Rest>
string array_debug_impl(const Array& a, First first, Rest... rest) {
string current = "[" + to_string(first) + "]";
string next = array_debug_impl(a, rest...);
return current + next;
}
template <typename T>
decltype(auto) get_nested(T&& first) {
return forward<T>(first);
}
template <typename T, typename U, typename... Args>
decltype(auto) get_nested(T&& first, U&& second, Args&&... args) {
return get_nested(forward<T>(first)[forward<U>(second)], forward<Args>(args)...);
}
template <typename Array, typename... Args>
string array_debug(const Array& a, Args... args) {
string indices_str = array_debug_impl(a, args...);
ostringstream value_oss;
value_oss << get_nested(a, args...);
return indices_str + " = " + value_oss.str();
}
ostream &operator<<(ostream &a, ostream &b) {
return b;
}
#if 1 // use debug macros
#define aedebug(first, ...) #first << array_debug(first, __VA_ARGS__)
#define spc << " " <<
#endif
#undef quick_io_int_length_limit
#undef quick_io_int_radix_type
#undef quick_io_length_type
}
using namespace quick_io;
// #define fast_ios_buffer_enough
// #define fast_is_buffer_enough
// #define fast_os_buffer_enough
#define fast_ios_only_int
// #define fast_is_only_int
// #define fast_os_only_int
#ifdef fast_ios_buffer_enough
#define fast_is_buffer_enough
#define fast_os_buffer_enough
#endif
#ifdef fast_ios_only_int
#define fast_is_only_int
#define fast_os_only_int
#endif
template<size_t buffer_size = 65536>
struct fast_reader_t {
// short, int, long, long long, __int128
// unsigned short, int, long, long long, __int128
// very safe if there are no overflow
size_t pos;
unsigned char c;
unsigned char in_buffer[buffer_size];
inline fast_reader_t() : pos(0), c(EOF) {
for (size_t i = fread(in_buffer, 1, buffer_size, stdin); i < buffer_size; i++) {
in_buffer[i] = EOF;
}
}
inline unsigned char &get() {
#ifndef fast_is_buffer_enough
if (pos < buffer_size) {
#endif
return c = in_buffer[pos++];
#ifndef fast_is_buffer_enough
}
for (size_t i = fread(in_buffer, 1, buffer_size, stdin); i < buffer_size; i++) {
in_buffer[i] = EOF;
}
return c = in_buffer[(pos = 0)++];
#endif
}
inline void unget() {
pos--;
}
template<typename T>
typename enable_if<is_integral<T>::value && is_unsigned<T>::value, fast_reader_t&>::type
inline operator>>(T &x) {
x = 0;
while ((c = get()) < '0' || c > '9');
do {
x = (x << 3) + (x << 1) + (c ^ '0');
} while ((c = get()) >= '0' && c <= '9');
#ifndef fast_is_only_int
unget();
#endif
return *this;
}
template<typename T>
typename enable_if<is_integral<T>::value && is_signed<T>::value, fast_reader_t&>::type
inline operator>>(T &x) {
typename make_unsigned<T>::type x_ = 0;
bool sign = false;
while (((c = get()) < '0' || c > '9') && c != '-' && c != '+');
if (c == '-') {
sign = true;
c = get();
} else if (c == '+') {
c = get();
}
do {
x_ = (x_ << 3) + (x_ << 1) + (c ^ '0');
} while ((c = get()) >= '0' && c <= '9');
x = x_;
if (sign) {
x = -x;
}
#ifndef fast_is_only_int
unget();
#endif
return *this;
}
};
template<size_t buffer_size = 65536>
struct fast_writer_t {
// short, int, long, long long, __int128
// unsigned short, int, long, long long, __int128
size_t pos;
unsigned char out_buffer[buffer_size];
inline fast_writer_t() : pos(0) {}
inline ~fast_writer_t() {
if (pos) {
flush();
}
}
inline void flush() {
__builtin_fwrite(out_buffer, 1, pos, stdout);
pos = 0;
}
inline void put(unsigned char c) {
out_buffer[pos++] = c;
#ifndef fast_os_buffer_enough
if (pos == buffer_size) {
flush();
}
#endif
}
template<typename T>
typename enable_if<is_integral<T>::value && is_unsigned<T>::value, fast_writer_t&>::type
inline operator<<(const T &x) {
if (x >= T(10)) {
*this << x / T(10);
}
put('0' ^ x % T(10));
return *this;
}
template<typename T>
typename enable_if<is_integral<T>::value && is_signed<T>::value, fast_writer_t&>::type
inline operator<<(const T &x) {
if (x >= T(0)) {
return *this << (typename make_unsigned<T>::type)x;
} else {
put('-');
return *this << (typename make_unsigned<T>::type)(-x);
}
}
};
fast_reader_t<> fast_reader;
fast_writer_t<> fast_writer;
#define K 500
#define block_L(x) (((x) - 1) / K * K + 1)
#define block_R(x) min(n, (((x) - 1) / K + 1) * K)
#define block_id(x) (((x) - 1) / K)
#define block_id2L(x) ((x) * K + 1)
#define block_id2R(x) min(n, ((x) + 1) * K)
int n, q, a[1000005], nxt[1000005];
bool all_out[1000005];
int tag[1000005];
int small_jump(int x)
{
return max(1, a[x] - tag[block_id(x)]);
}
int big_jump(int x)
{
return max(0, all_out[block_id(x)] ? a[x] - tag[block_id(x)] : nxt[x]);
}
void build(int L, int R) {
// cout << "build(" << L << "," << R << ")" << endl;
int bid = block_id(L);
all_out[bid] = 1;
for (int i = L; i <= R; i++)
{
if (a[i] < L)
{
nxt[i] = a[i];
}
else
{
all_out[bid] = 0;
nxt[i] = nxt[a[i]];
}
}
tag[bid] = 0;
}
signed main() {
fast_reader >> n >> q;
for (int i = 2; i <= n; i++) {
fast_reader >> a[i];
}
for (int L = 1, R = K; L <= n; L += K, R += K) {
build(L, min(n, R));
}
// cout << adebug(a, 1, n) << endl;
// cout << adebug(nxt, 1, n) << endl;
int x, y, k, op, lastans = 0;
while (q--) {
fast_reader >> op >> x >> y;
x ^= lastans;
y ^= lastans;
// cout << op << " " << x << " " << y << endl;
if (op == 2) {
// cout << adebug(a, 1, n) << endl;
// cout << adebug(nxt, 1, n) << endl;
while (true)
{
int bjx = big_jump(x);
int bjy = big_jump(y);
// cout << x << "," << y << " -> " << bjx << "," << bjy << endl;
if (bjx > bjy)
{
x = bjx;
}
else if (bjy < bjx)
{
y = bjy;
}
else
{
break;
}
}
// cout << x << " " << y << endl;
while (x != y)
{
// cout << x << " " << y << " -> " << small_jump(x) << " " << small_jump(y) << endl;
int jx = small_jump(x);
int jy = small_jump(y);
if (jx >= jy)
{
x = jx;
}
if (jy >= jx)
{
y = jy;
}
}
// cout << x << endl;
fast_writer << (lastans = x);
fast_writer.put('\n');
} else {
fast_reader >> k;
k ^= lastans;
int lb = block_id(x);
int rb = block_id(y);
if (lb == rb)
{
// cout << "in one block" << endl;
if (all_out[lb] && tag[lb])
{
for (int i = block_id2L(lb), i_e = block_id2R(lb); i <= i_e; i++)
{
a[i] -= tag[lb];
if (a[i] < 1)
{
a[i] = 1;
}
}
}
for (int i = x; i <= y; i++)
{
a[i] -= k;
if (a[i] < 1)
{
a[i] = 1;
}
}
build(block_id2L(lb), block_id2R(lb));
continue;
}
for (int b_id = lb + 1; b_id < rb; b_id++)
{
if (all_out[b_id])
{
tag[b_id] += k;
}
else
{
int i_b = block_id2L(b_id);
int i_e = block_id2R(b_id);
// cout << i_b << "~" << i_e << " rebuild" << endl;
for (int i = i_b; i <= i_e; i++)
{
a[i] -= k;
if (a[i] < 1)
{
a[i] = 1;
}
}
build(i_b, i_e);
}
}
int i_e = block_id2R(lb);
for (int i = x; i <= i_e; i++)
{
a[i] -= k;
if (a[i] < 1)
{
a[i] = 1;
}
}
build(block_id2L(lb), i_e);
for (int i = block_id2L(rb); i <= y; i++)
{
a[i] -= k;
if (a[i] < 1)
{
a[i] = 1;
}
}
build(block_id2L(rb), block_id2R(lb));
}
}
return 0;
}