[WC2021] 表达式求值
[题目链接]
[题解]
首先让我们解决一个简单的问题 :
注意到 \(K\) 很小 , 那么不妨维护 \(f_{i , S}\) 表示 \(i\) 号生物的每个位置是否都比 \(S\) 中每个元素的值大。
用 \(bitset\) 维护 \(f\) , 查询时 , 从大到小枚举值即可。
时间复杂度 : \(O(\frac{Q2 ^ {K}}{w})\)
解决这个问题的关键是 : 每个位置的值都是由 \(K\) 个初始数组中的元素得到的 , 而 \(K\) 又很小 , 因此可以通过压缩状态之类的方法求解。
回到本题 , 首先不妨建出表达式树。这是一棵高度为 \(O(N)\) 的树 , 叶子节点维护的是位置 , 而非叶节点则为操作。( 详见 [代码] )
令 \(f_{u , S}\) 表示 \(u\) 节点的值严格大于 \(S\) 中每个数的方案数。转移只需分别讨论两个儿子节点的情况。
回答询问时进行容斥即可。
时间复杂度 \(O(N2 ^ {M})\)
[代码]
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i , l , r) for (int i = (l); i < (r); ++i)
const int MN = 5e4 + 5, mod = 1e9 + 7;
typedef pair < int, int > pii;
#define mp make_pair
int N, M, cnt, top, len, stk[MN], pre[MN], f[MN][2], g[1 << 12], a[12][MN], size,
val[MN], child[MN][2];
char s[MN];
inline void inc(int &x, int y) {
x = x + y < mod ? x + y : x + y - mod;
}
inline void dec(int &x, int y) {
x = x - y >= 0 ? x - y : x - y + mod;
}
inline int get(int x) {
if (s[x] == '<')
return -1;
if (s[x] == '>')
return -2;
return -3;
}
inline int build(int l, int r) {
int cur = ++size;
if (s[r] == ')' && pre[r] == l)
++l, --r;
if (l == r)
return val[cur] = s[l] - '0', cur;
if (s[r] == ')') {
val[cur] = get(pre[r] - 1);
child[cur][0] = build(l, pre[r] - 2);
child[cur][1] = build(pre[r], r);
} else {
val[cur] = get(r - 1);
child[cur][0] = build(l, r - 2), child[cur][1] = build(r, r);
}
return cur;
}
int main() {
scanf("%d%d", &N, &M);
for (int i = 0; i < M; ++i)
for (int j = 1; j <= N; ++j)
scanf("%d", &a[i][j]);
scanf("%s", s + 1);
len = strlen(s + 1);
for (int i = 1; i <= len; ++i)
if (s[i] == '(')
stk[++top] = i;
else if (s[i] == ')')
pre[i] = stk[top--];
build(1, len);
for (int s = 0; s < (1 << M); ++s) {
for (int u = size; u >= 1; --u) {
f[u][0] = f[u][1] = 0;
if (val[u] >= 0)
f[u][s >> val[u] & 1] = 1;
else {
if (val[u] != -2) {
inc(f[u][0], 1ll * (f[child[u][0]][0] + f[child[u][0]][1]) * (f[child[u][1]][0] + f[child[u][1]][1]) % mod);
dec(f[u][0], 1ll * f[child[u][0]][1] * f[child[u][1]][1] % mod);
inc(f[u][1], 1ll * f[child[u][0]][1] * f[child[u][1]][1] % mod);
}
if (val[u] != -1) {
inc(f[u][1], 1ll * (f[child[u][0]][0] + f[child[u][0]][1]) * (f[child[u][1]][0] + f[child[u][1]][1]) % mod);
dec(f[u][1], 1ll * f[child[u][0]][0] * f[child[u][1]][0] % mod);
inc(f[u][0], 1ll * f[child[u][0]][0] * f[child[u][1]][0] % mod);
}
}
}
g[s] = f[1][0];
}
int ans = 0;
for (int i = 1; i <= N; ++i) {
vector < pii > vec;
for (int j = 0; j < M; ++j)
vec.emplace_back(mp(a[j][i], j));
sort(vec.begin(), vec.end());
int s = (1 << M) - 1;
for (int j = 0; j < M; ++j) {
int ns = s ^ (1 << vec[j].second);
inc(ans, 1ll * (g[ns] + mod - g[s]) * vec[j].first % mod);
s = ns;
}
}
printf("%d\n", ans);
return 0;
}