首页 > 代码库 > [Gym 100228] Graph of Inversions
[Gym 100228] Graph of Inversions
题意
给定长度为 $n$ 的序列 $A = \left\{ a_1, a_2, ..., a_n \right\}$ .
我们定义其逆序图 $G$ : 对于 $i < j$ , $i, j$ 之间存在连边 $\Leftrightarrow a_i > a_j$ .
给定一个序列的逆序图, 求有多少个点集 $S$ , 满足 $S$ 既是独立集, 又是覆盖集.
$n \le 1000$ .
分析
我们考虑探究逆序图与原序列的关系.
点集 $S$ 在逆序图中是独立集, 当且仅当在原序列中单调不降.
点集 $S$ 在逆序图中是覆盖集, 当且仅当对于任意相邻的 $i, j$ , $i < j$ , 满足 $\forall k \in (i, j), a_i > a_k 或 a_k > a_j$ .
我们考虑进行DP.
可以利用单调性优化到 $O(n ^ 2)$ , 判定 $j$ 是否合法的时间复杂度为 $O(1)$ .
实现
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 #define P(i, a, b) for (register int i = (a); i >= (b); i--) 7 #define LL long long 8 inline int rd(void) { 9 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 10 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 11 } 12 13 const int N = 1005; 14 15 int n, m; 16 bool g[N][N]; 17 18 LL f[N]; 19 LL res; 20 21 int main(void) { 22 #ifndef ONLINE_JUDGE 23 freopen("100228.in", "r", stdin); 24 #endif 25 26 n = rd(), m = rd(); 27 F(i, 1, m) { 28 int x = rd()+1, y = rd()+1; 29 g[x][y] = g[y][x] = true; 30 } 31 F(i, 0, n+1) g[i][n+1] = g[n+1][i] = true; 32 33 f[0] = 1; 34 F(i, 1, n) { 35 int w = n+1; 36 P(j, i-1, 0) 37 if (!g[j][i] && g[j][w]) 38 f[i] += f[j], w = j; 39 } 40 int w = n+1; 41 for (int j = n; j >= 1; j--) 42 if (g[j][w]) 43 res += f[j], w = j; 44 printf("%lld\n", res); 45 46 return 0; 47 }
[Gym 100228] Graph of Inversions
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。