# 【LOJ2261】「CTSC2017」密钥

【题目链接】

【思路要点】

• 使用一个简单的扫描线可以求出 $X$ 在每个位置处的特征值。
• 时间复杂度 $O(N)$

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e7 + 5;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
bool p[MAXN];
int seed, n, k, s;
int getrand() {
seed = ((seed * 12321) ^ 9999) % 32768;
return seed;
}
void generateData() {
scanf("%d%d%d", &k, &seed, &s);
int t = 0;
n = k * 2 + 1;
for (int i = 1; i <= n; i++) {
p[i] = getrand() >> 7 & 1;
t += p[i];
}
int i = 1;
while(t > k) {
while (p[i] == 0) i++;
p[i] = 0; t--;
}
while(t < k) {
while (p[i] == 1) i++;
p[i] = 1; t++;
}
}
int val[MAXN];
int solve(int x, bool type) {
memset(val, 0, sizeof(val));
int cipher = k + 2, now = cipher, pos = cipher;
for (int i = 1; i <= n; i++)
if (p[i] ^ type) val[++pos]++;
else pos--;
int sum = 0;
for (int i = now + 1; i <= n + 2; i++)
sum += val[i];
for (int i = 1; i <= n; i++) {
if (p[i] ^ type) sum -= val[++now], val[now]--;
else sum += val[now--];
if (!p[i] && sum == x) return i;
if (p[i] ^ type) {
val[++pos]++;
if (pos > now) sum++;
} else pos--;
}
assert(false);
return -1;
}
int main() {
generateData();
printf("%d\n%d\n%d\n", solve(0, false), solve(s, false), solve(s, true));
return 0;
}