nn个栈,mm次操作

区间压数,单点弹栈,求区间栈顶和

强制在线

n,m5×105n, m\le 5\times10^5

UOJ218

Solution

19-8-27-1

本来想只用一个主席树维护的

搞了一晚上不晓得怎么维护,网上的代码也看不懂

就弃了

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <bits/stdc++.h>

#define x first
#define y second
#define y1 Y1
#define y2 Y2
#define mp make_pair
#define pb push_back
#define DEBUG(x) cout << #x << " = " << x << endl;

using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

template <typename T> inline int Chkmax (T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline int Chkmin (T &a, T b) { return a > b ? a = b, 1 : 0; }
template <typename T> inline T read ()
{
T sum = 0, fl = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fl = -1;
for (; isdigit(ch); ch = getchar()) sum = (sum << 3) + (sum << 1) + ch - '0';
return sum * fl;
}

inline void proc_status ()
{
ifstream t ("/proc/self/status");
cerr << string (istreambuf_iterator <char> (t), istreambuf_iterator <char> ()) << endl;
}

const int Maxn = 5e5 + 100;

int N, M, type;
int O[Maxn];

namespace CMT
{
#define mid ((l + r) >> 1)
#define ls node[o].ch[0]
#define rs node[o].ch[1]
#define lson ls, l, mid
#define rson rs, mid + 1, r
struct info
{
int ch[2];
pii val;
info () { val = mp (0, -1); }
} node[Maxn * 80];
int node_cnt;

inline void build (int &o, int l, int r)
{
o = ++node_cnt;
if (l == r) return ;
build (lson), build (rson);
}

inline void update (int pre, int &o, int l, int r, int x, int y, pii val)
{
o = ++node_cnt; node[o] = node[pre];
if (!pre) node[o].val = mp (0, -1);
if (x <= l && r <= y) { node[o].val = val; ls = rs = 0; return ; }
if (x <= mid) update (node[pre].ch[0], lson, x, y, val);
if (y > mid) update (node[pre].ch[1], rson, x, y, val);
}

inline pii query (int o, int l, int r, int x)
{
if (!o) return mp (0, -1);
if (l == r) return node[o].val;
pii ans = mp (0, -1);
if (x <= mid) ans = query (lson, x);
else ans = query (rson, x);
if (ans.y < 0) ans = node[o].val;
return ans;
}

#undef mid
#undef ls
#undef rs
#undef lson
#undef rson

}

namespace SEG
{
#define mid ((l + r) >> 1)
#define ls o << 1
#define rs o << 1 | 1
#define lson ls, l, mid
#define rson rs, mid + 1, r

struct info
{
int tag, sum;
} node[Maxn << 2];

inline void push_up (int o) { node[o].sum = node[ls].sum + node[rs].sum; }

inline void push_down (int o, int l, int r)
{
int &t = node[o].tag;
if (!t) return ;
node[ls].tag = node[rs].tag = t;
node[ls].sum = t * (mid - l + 1), node[rs].sum = t * (r - mid);
t = 0;
}

inline int query (int o, int l, int r, int x, int y)
{
if (x <= l && r <= y) return node[o].sum;
push_down (o, l, r);
int ans = 0;
if (x <= mid) ans += query (lson, x, y);
if (y > mid) ans += query (rson, x, y);
return ans;
}

inline void update (int o, int l, int r, int x, int y, int val)
{
if (x <= l && r <= y) { node[o].tag = val, node[o].sum = (r - l + 1) * val; return ; }
push_down (o, l, r);
if (x <= mid) update (lson, x, y, val);
if (y > mid) update (rson, x, y, val);
push_up (o);
}

#undef mid
#undef ls
#undef rs
#undef lson
#undef rson

}


inline void Solve ()
{
CMT :: build (O[0], 1, N);
int ans = 0;
for (int i = 1; i <= M; ++i)
{
int op = read<int>();
if (op == 1)
{
int l = (read<int>() + ans * type) % N + 1, r = (read<int>() + ans * type) % N + 1;
if (l > r) swap (l, r);
O[i] = O[i - 1];
printf("%d\n", ans = SEG :: query (1, 1, N, l, r));
}
else if (op == 2)
{
int l = (read<int>() + ans * type) % N + 1;
int x = CMT :: query (O[i - 1], 1, N, l).y;
pii now = CMT :: query (O[x], 1, N, l);
if (now.y < 0) now.y = 0;
CMT :: update (O[i - 1], O[i], 1, N, l, l, now);
SEG :: update (1, 1, N, l, l, now.x);
}
else
{
int l = (read<int>() + ans * type) % N + 1, r = (read<int>() + ans * type) % N + 1, x = read<int>();
if (l > r) swap (l, r);
SEG :: update (1, 1, N, l, r, x);
CMT :: update (O[i - 1], O[i], 1, N, l, r, mp (x, i - 1));
}
}
}

inline void Input ()
{
N = read<int>(), M = read<int>(), type = read<int>();
}

int main()
{

#ifndef ONLINE_JUDGE
freopen("A.in", "r", stdin);
freopen("A.out", "w", stdout);
#endif

Input ();
Solve ();

return 0;
}