QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#465154 | #8819. CNOI Knowledge | 中国入民小学附属信息I队 (Zicheng Wang, Shubang Liu, Minkai Shao)# | WA | 118ms | 3732kb | C++14 | 5.6kb | 2024-07-06 17:42:19 | 2024-07-06 17:42:19 |
Judging History
answer
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cassert>
typedef long long ll;
typedef double lf;
#define DEBUG 1
struct IO
{
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
char buf[MAXSIZE], *p1, *p2;
char pbuf[MAXSIZE], *pp;
#if DEBUG
#else
IO() : p1(buf), p2(buf), pp(pbuf) {}
~IO() {fwrite(pbuf, 1, pp - pbuf, stdout);}
#endif
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) ? ' ' : *p1++)
#define blank(x) (x == ' ' || x == '\n' || x == '\r' || x == '\t')
template <typename T>
void Read(T &x)
{
#if DEBUG
std::cin >> x;
#else
bool sign = 0; char ch = gc(); x = 0;
for (; !isdigit(ch); ch = gc())
if (ch == '-') sign = 1;
for (; isdigit(ch); ch = gc()) x = x * 10 + (ch ^ 48);
if (sign) x = -x;
#endif
}
void Read(char *s)
{
#if DEBUG
std::cin >> s;
#else
char ch = gc();
for (; blank(ch); ch = gc());
for (; !blank(ch); ch = gc()) *s++ = ch;
*s = 0;
#endif
}
void Read(char &c) {for (c = gc(); blank(c); c = gc());}
void Push(const char &c)
{
#if DEBUG
putchar(c);
#else
if (pp - pbuf == MAXSIZE) fwrite(pbuf, 1, MAXSIZE, stdout), pp = pbuf;
*pp++ = c;
#endif
}
template <typename T>
void Write(T x)
{
if (x < 0) x = -x, Push('-');
static T sta[35];
int top = 0;
do sta[top++] = x % 10, x /= 10; while (x);
while (top) Push(sta[--top] ^ 48);
}
template <typename T>
void Write(T x, char lst) {Write(x), Push(lst);}
} IO;
#define Read(x) IO.Read(x)
#define Write(x, y) IO.Write(x, y)
#define Put(x) IO.Push(x)
using namespace std;
const int MAXN = 1e3 + 10;
int n, m = 1;
int s[MAXN];
int QT;
inline int Query(int l, int r)
{
QT++; assert(QT <= 10000);
cout << "? " << l << ' ' << r << endl;
int res; cin >> res;
return res;
}
int b[MAXN], z[MAXN];
inline void GetZ(int len)
{
z[1] = 0;
for (int i = 2, l = 0, r = 0; i <= len; i++)
{
int k = (i > r ? 0 : min(r - i + 1, z[i - l + 1]));
while (i + k <= len && b[i + k] == b[k + 1]) k++;
z[i] = k;
if (i + k - 1 > r) l = i, r = i + k - 1;
}
}
int st[MAXN], top;
inline void FindAllAppear(int len, int k)
{
top = 0;
if (k == 0)
{
for (int i = 0; i < len; i++) st[++top] = i;
return;
}
for (int i = len; i >= 1; i--) b[len - i + 1] = s[i];
GetZ(len);
for (int i = len; i >= 2; i--)
if (z[i] >= k) st[++top] = len - i + 1;
}
bool C;
int sa[MAXN], rk[MAXN], p[MAXN << 1], cnt[MAXN], ht[MAXN];
inline int Calc(int len)
{
int M = m;
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= len; i++) cnt[rk[i] = b[i]]++;
for (int i = 2; i <= M; i++) cnt[i] += cnt[i - 1];
for (int i = 1; i <= len; i++) sa[++cnt[rk[i] - 1]] = i;
for (int w = 1; w < len; w <<= 1)
{
int tot = 0;
for (int i = len - w + 1; i <= len; i++) p[++tot] = i;
for (int i = 1; i <= len; i++)
if (sa[i] > w) p[++tot] = sa[i] - w;
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= len; i++) cnt[rk[i]]++;
for (int i = 2; i <= M; i++) cnt[i] += cnt[i - 1];
for (int i = 1; i <= len; i++) sa[++cnt[rk[p[i]] - 1]] = p[i];
memcpy(p, rk, sizeof(rk));
M = 0;
for (int i = 1; i <= len; i++)
rk[sa[i]] = (p[sa[i]] == p[sa[i - 1]] && p[sa[i] + w] == p[sa[i - 1] + w] ? M : ++M);
if (M == len) break;
}
for (int i = 1, j = 0; i <= len; i++)
{
if (j) j--;
if (rk[i] == 1) continue;
while (i + j <= len && sa[rk[i] - 1] + j <= len && b[i + j] == b[sa[rk[i] - 1] + j]) j++;
ht[rk[i]] = j;
}
int res = len * (len + 1) / 2;
for (int i = 2; i <= len; i++) res -= ht[i];
// for (int i = 1; i <= len; i++) cout << b[i] << ' '; cout << '\n';
// for (int i = 1; i <= len; i++) cout << rk[i] << ' '; cout << '\n';
// for (int i = 1; i <= len; i++) cout << ht[i] << ' '; cout << '\n';
return res;
}
inline bool Check(int len, int l, int k)
{
for (int i = l; i < len; i++) b[i - l + 1] = s[i];
// if (len == 10 && l == 5) C = 1;
int lst = Calc(len - l);
// if (len == 10 && l == 5) C = 0;
int cur = Query(l, len);
int mxlen = (len - l) - (cur - lst);
// cout << "lst: " << lst << " Chk: " << mxlen << ' ' << k << "\n";
return mxlen >= k;
}
int main()
{
#if DEBUG
#else
ios::sync_with_stdio(0), cin.tie(0);
#endif
cin >> n;
s[1] = 1; int lstqry = 1;
for (int i = 2; i <= n; i++)
{
int curqry = Query(1, i), mxlen = i - (curqry - lstqry);
// cerr << "# " << i << ' ' << curqry << ' ' << lstqry << ' ' << mxlen << '\n';
lstqry = curqry;
if (mxlen == 0) {s[i] = ++m; continue;}
mxlen--;
FindAllAppear(i - 1, mxlen);
// for (int i = 1; i <= top; i++) cout << st[i] << ' '; cout << "\n";
int l = 1, r = top, mid, apr;
while (l <= r)
{
mid = l + r >> 1;
if (Check(i, st[mid] - mxlen + 1, mxlen)) apr = mid, l = mid + 1;
else r = mid - 1;
}
// cout << "## " << i << ' ' << st[apr] << "\n";
s[i] = s[st[apr] + 1];
}
cout << "! ";
for (int i = 1; i <= n; i++) cout << s[i] << ' '; cout << endl;
return 0;
}
詳細信息
Test #1:
score: 100
Accepted
time: 1ms
memory: 3552kb
input:
12 3 6 10 15 21 27 15 27 20 34 14 6 9 43 52 19 9 5 2 62 25 8 5 72 31 13
output:
? 1 2 ? 1 3 ? 1 4 ? 1 5 ? 1 6 ? 1 7 ? 3 7 ? 1 7 ? 2 7 ? 1 8 ? 4 8 ? 6 8 ? 5 8 ? 1 9 ? 1 10 ? 5 10 ? 7 10 ? 8 10 ? 9 10 ? 1 11 ? 5 11 ? 8 11 ? 9 11 ? 1 12 ? 5 12 ? 8 12 ! 1 2 3 4 5 6 2 5 7 7 5 6
result:
ok Accepted. 26 queries used.
Test #2:
score: -100
Wrong Answer
time: 118ms
memory: 3732kb
input:
1000 3 5 5 2 7 3 11 7 11 16 8 5 2 21 21 3 27 7 27 34 21 15 41 19 48 23 57 19 4 66 29 5 75 6 84 7 96 13 47 15 108 55 124 27 15 11 7 140 61 140 156 156 172 172 188 188 208 77 59 50 41 229 128 41 26 251 213 26 20 273 233 24 295 253 28 319 87 26 343 232 100 369 213 45 17 395 52 24 423 96 47 451 451 108 ...
output:
? 1 2 ? 1 3 ? 1 3 ? 2 3 ? 1 4 ? 2 4 ? 1 5 ? 2 5 ? 1 5 ? 1 6 ? 3 6 ? 4 6 ? 5 6 ? 1 7 ? 1 7 ? 5 7 ? 1 8 ? 5 8 ? 1 8 ? 1 9 ? 3 9 ? 4 9 ? 1 10 ? 4 10 ? 1 11 ? 4 11 ? 1 12 ? 6 12 ? 9 12 ? 1 13 ? 5 13 ? 9 13 ? 1 14 ? 9 14 ? 1 15 ? 9 15 ? 1 16 ? 10 16 ? 5 16 ? 9 16 ? 1 17 ? 5 17 ? 1 18 ? 10 18 ? 13 18 ? 14...
result:
wrong answer Wrong Answer.