题解:P16497 东风归故里,托此报微酬
唐氏做法。建议不要学习,更不要场写。
但是如果你想要卡掉 findnext 的那个
理论复杂度最优,实际效率洛谷第三。
原题就是让你求序列中的非严格前缀最大值个数。
因为只有增大而没有减小,所以每次操作
设操作前,序列中非严格前缀最大值的位置是
如果
否则,把
由于每次操作最多会增加 set 维护非严格前缀最大值位置集合,你就会了
看一眼时限,450ms 的意思一定是所有测试点加起来一共 450ms,这个做法显然是过不了的。考虑卡常。
考虑用 bool 表示每个位置是否是非严格前缀最大值位置。这样你可以每 bool 压成一个 unsigned long long,做到
又考虑到你可以再次用一个长度为 bool 数组表示每个 unsigned long long 是否不为 unsigned long long 数组来表示这个 bool 数组,如此反复下去。这样最多套娃三层,因为
#include <cstdio>
namespace FastIn
{
const int S = 4e6 + 7;
char *p1, *p2, buf[S];
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, S, stdin), p1 == p2) ? EOF : *p1++)
template <typename _T>
inline void read(_T &x)
{
x = 0;
char c = gc();
while (c < '0' || c > '9')
c = gc();
for (; c >= '0' && c <= '9'; c = gc())
x = (x << 3) + (x << 1) + (c & 15);
}
#undef gc
}
using FastIn::read;
const int MAXN = 2e5 + 7;
int n, m, c, ans;
long long a[MAXN];
namespace FS
{
unsigned long long b[3][MAXN];
inline void update(int x, const bool &val)
{
if (val)
b[0][x >> 6] |= 1ull << (x & 63), x >>= 6,
b[1][x >> 6] |= 1ull << (x & 63), x >>= 6,
b[2][x >> 6] |= 1ull << (x & 63);
else
{
b[0][x >> 6] &= ~(1ull << (x & 63));
if (b[0][x >> 6])
return;
x >>= 6, b[1][x >> 6] &= ~(1ull << (x & 63));
if (b[1][x >> 6])
return;
x >>= 6, b[2][x >> 6] &= ~(1ull << (x & 63));
}
}
inline int findprev(int x)
{
int i = x >> 6;
unsigned long long t = (b[0][i] << (63 - (x & 63))) >> (63 - (x & 63));
if (t)
return (i << 6) + 63 - __builtin_clzll(t);
x = i - 1, i = x >> 6, t = (b[1][i] << (63 - (x & 63))) >> (63 - (x & 63));
if (!t)
x = i - 1, i = x >> 6, t = (b[2][i] << (63 - (x & 63))) >> (63 - (x & 63)),
i = (i << 6) + 63 - __builtin_clzll(t), t = b[1][i];
i = (i << 6) + 63 - __builtin_clzll(t), t = b[0][i];
return (i << 6) + 63 - __builtin_clzll(t);
}
inline int findnext(int x)
{
int i = x >> 6;
unsigned long long t = (b[0][i] >> (x & 63)) << (x & 63);
if (t)
return (i << 6) + __builtin_ctzll(t);
x = i + 1, i = x >> 6, t = (b[1][i] >> (x & 63)) << (x & 63);
if (!t)
x = i + 1, i = x >> 6, t = (b[2][i] >> (x & 63)) << (x & 63),
i = (i << 6) + __builtin_ctzll(t), t = b[1][i];
i = (i << 6) + __builtin_ctzll(t), t = b[0][i];
return (i << 6) + __builtin_ctzll(t);
}
}
int main()
{
read(n), read(m), read(c);
long long premax = 0;
for (int i = 1; i <= n; ++i)
read(a[i]), a[i] >= premax && (FS::update(i, true), premax = a[i], ++ans);
FS::update(0, true), FS::update(n + 1, true), a[n + 1] = 0x3f3f3f3f3f3f3f3fll;
for (int t = 1, p, x, lst = 0; t <= m; ++t)
{
read(p), read(x), p ^= (c * lst) % 3, a[p] += x;
if (a[p] < a[FS::findprev(p)])
{
printf("%d\n", lst = ans);
continue;
}
if (FS::findnext(p) != p)
FS::update(p, true), ++ans;
long long ap = a[p];
while (ap > a[FS::findnext(p + 1)])
p = FS::findnext(p + 1), FS::update(p, false), --ans;
printf("%d\n", lst = ans);
}
return 0;
}