题目简述
求一个只含三目运算符和数的含 x x x 式子代入若干 x x x 的值。
做法
观察样例。
我们发现,每次判断都是先看红色部分。如果结果为真判断黄色,为假判断蓝色。接下来同理。
判断过程可以看作一个树形图。
每个询问从上往下 dfs 即可。
可以获得
72
p
t
s
72pts
72pts 的高分。
为什么被卡了?
因为如果树是一条链,单次查询为
O
(
n
)
O(n)
O(n),于是 TLE 了。
考虑离线,把所有询问读进来,并排序。
每次到一个结点时,二分判断那部分往左走,哪部分往右走。
这回不会再被卡了。时间复杂度
O
(
n
log
(
q
)
)
O(n \log(q))
O(nlog(q))。
可以获得
100
p
t
s
100pts
100pts 的高分。
代码
代码放在下面,建议大家不要 Ctrl c + Ctrl v,自己写一遍会有更大的进步。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2000010, M = 300010;
int n, m, q;
char s[N];
int h[M], e[M], val[M], ne[M], idx, tot;
int w[M], st[M];
struct Query
{
int id, x;
bool operator <(const Query &W)
{
return x < W.x;
}
}query[M];
int res[M];
void add(int a, int b, int c)
{
e[tot] = b, val[tot] = c, ne[tot] = h[a], h[a] = tot ++ ;
}
int dfs1(int& u)
{
if (s[u] >= '0' && s[u] <= '9')
{
w[ ++ idx] = s[u] - '0', st[idx] = 1;
for (u ++ ; u <= n && s[u] >= '0' && s[u] <= '9'; u ++ )
w[idx] = w[idx] * 10 + s[u] - '0';
return idx;
}
else
{
u ++ ;
++ idx;
int v = idx;
if (s[u] == '>') st[v] = 2;
else st[v] = 3;
u ++ ;
w[v] = s[u] - '0';
for (u ++ ; u <= n && s[u] >= '0' && s[u] <= '9'; u ++ )
w[v] = w[v] * 10 + s[u] - '0';
u ++ ;
int left = dfs1(u);
u ++ ;
int right = dfs1(u);
add(v, left, 0), add(v, right, 1);
return v;
}
}
void dfs2(int u, int l, int r)
{
if (st[u] == 1)
{
for (int i = l; i <= r; i ++ )
res[query[i].id] = w[u];
return;
}
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (st[u] == 2) // '>'
{
if (val[i] == 0) // '>'
{
int L = l, R = r + 1;
while (L < R)
{
int mid = L + R >> 1;
if (query[mid].x > w[u]) R = mid;
else L = mid + 1;
}
if (L != r + 1) dfs2(j, L, r);
}
else // '<='
{
int L = l - 1, R = r;
while (L < R)
{
int mid = L + R + 1 >> 1;
if (query[mid].x <= w[u]) L = mid;
else R = mid - 1;
}
if (R != l - 1) dfs2(j, l, R);
}
}
if (st[u] == 3) // '<'
{
if (val[i] == 0) // '<'
{
int L = l - 1, R = r;
while (L < R)
{
int mid = L + R + 1 >> 1;
if (query[mid].x < w[u]) L = mid;
else R = mid - 1;
}
if (R != l - 1) dfs2(j, l, R);
}
else // '>=';
{
int L = l, R = r + 1;
while (L < R)
{
int mid = L + R >> 1;
if (query[mid].x >= w[u]) R = mid;
else L = mid + 1;
}
if (L != r + 1) dfs2(j, L, r);
}
}
}
}
int main()
{
scanf("%d%d", &m, &q);
scanf("%s", s + 1);
n = strlen(s + 1);
memset(h, -1, sizeof h);
int first = 1;
int root = dfs1(first);
for (int i = 0; i < q; i ++ )
{
int x;
scanf("%d", &x);
query[i] = {i, x};
}
sort(query, query + q);
dfs2(root, 0, q - 1);
for (int i = 0; i < q; i ++ ) printf("%d\n", res[i]);
return 0;
}