题解【No cost too great】
传送门
前置知识:
差分,容斥。
题意:
- 给出一张有向图,对房间
i 有若干条边连向区间[l_i,r_i] 中的所有点。 -
分析:
是一道容斥+dp+小幅度卡空间题。
Subtask0:
dfs 暴力搜索。
Subtask2:
先来看看没有容斥、不卡空间的 dp 该怎么做。
考虑一个 dp 数组
for(int k=1; k<=M; ++k) {
for(int s=1; s<=n; ++s) {
for(int t=1; t<=n; ++t) {
f[k][s][L[t]]+=f[k-1][s][t];
f[k][s][R[t]+1]-=f[k-1][s][t];
}
for(int t=1; t<=n; ++t) {
f[k][s][t]+=f[k][s][t-1];
}
}
}
询问可以在线回答:
while(q--) {
int a=read(), b=read(), c=read(), m=read();//这里的c暂时没用
printf("%d\n", f[m][a][b]);
}
Subtask3:
加入容斥,显然不经过点
for(int k=1; k<=M; ++k) {
for(int s=1; s<=n; ++s) {
for(int t=1; t<=n; ++t) {
f[k][s][L[t]]+=f[k-1][s][t], f[k][s][R[t]+1]-=f[k-1][s][t];
g[k][s][L[t]]+=g[k-1][s][t], g[k][s][R[t]+1]-=g[k-1][s][t];
}
for(int t=1; t<=n; ++t) {
f[k][s][t]+=f[k][s][t-1];
g[k][s][t]+=g[k][s][t-1];
}
g[k][s][s]=0;
}
}
询问仍然是在线回答:
while(q--) {
int a=read(), b=read(), c=read(), m=read(), ans=f[m][a][b];
for(int i=0; i<=m; ++i) ans-=f[i][a][c]*g[m-i][c][b];
printf("%d\n", ans);
}
Subtask4:
不出意外的话,此时的数组大小在 200MB 上下,完全无法通过 128MB 的限制。但是询问是可以离线的,意味着我们并不需要将
#define rep(i, a, b) ...
inline int read(){...};
const int N=502, M=100, Q=1e5+1;
int n, q, L[N], R[N], f[M+2][N][N], g[2][N][N];
struct Que {
int a, b, c, m, ans;
inline void sol(int k) {
if(k<=m) ans-=f[m-k][a][c]*g[k&1][c][b];
}
} que[Q];
inline Que get() {
int a=read(), b=read(), c=read(), m=read();
return Que(a, b, c, m, f[m][a][b]);
}
int main() {
//输入
n=read(), q=read();
rep(i, 1, n) {
L[i]=read(), R[i]=read();
f[0][i][i]=g[0][i][i]=1;
if(!L[i]) L[i]=1;
}
//计算数组 f
rep(k, 1, M) {
rep(s, 1, n) {
rep(t, 1, n) {
f[k][s][L[t]]+=f[k-1][s][t]);
f[k][s][R[t]+1]-=f[k-1][s][t];
}
rep(t, 1, n) {
f[k][s][t]+=f[k][s][t-1];
}
}
}
//输入与预处理询问
rep(i, 1, q) {
que[i]=get();
que[i].sol(0);
}
//计算数组 g 与答案
rep(k, 1, M) {
bool kk=k&1, tk=kk^1;
memset(g[kk], 0, sizeof(g[kk]));
rep(s, 1, n) {
rep(t, 1, n) {
g[kk][s][L[t]]+=g[tk][s][t];
g[kk][s][R[t]+1]-=g[tk][s][t];
}
rep(t, 1, n) {
g[kk][s][t]+=g[kk][s][t-1];
}
g[kk][s][s]=0;
}
rep(i, 1, q) que[i].sol(k);
}
//输出答案
rep(i, 1, q) printf("%d\n", que[i].ans);
}
时间复杂度为
其他的话
本题可以进一步对空间进行常数级别的优化,最后将空间控制在 54MB 上下,是通过只存储奇数步的