题解:CF2143D2 Inversion Graph Coloring (Hard Version)
题面转化
给定一个序列,问子序列中最长下降子序列长度小于等于
solution
首先,我们发现这道题并不关心子序列的最长下降子序列的长度,只关心子序列的最长下降子序列是否大于
对于这个状态我们可以写出转移方程。首先,只有
注意到,第一维的
假设我们枚举到第
这时我们又注意到,对于
这时我们又注意到,对于
然后我们就做完了,时间复杂度
code
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define N 2005
int n, a[N], tree1[N][N], tree2[N][N], ans;
inline void update1(int x, int y, int z) {
while(x <= n)
tree1[y][x] += z,
tree1[y][x] %= mod,
x += x & -x;
}
inline int query1(int x, int y) {
int ret = 0;
while(x)
ret += tree1[y][x],
ret %= mod, x -= x & -x;
return ret;
}
inline void update2(int x, int y, int z) {
while(x <= n)
tree2[x][y] += z,
tree2[x][y] %= mod,
x += x & -x;
}
inline int query2(int x, int y) {
int ret = 0;
while(x)
ret += tree2[x][y],
ret %= mod, x -= x & -x;
return ret;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--) {
cin >> n;
ans = 0;
for(int i = 1; i <= n; ++i) cin >> a[i];
for(int i = n; i; --i)
for(int j = n; j; --j)
tree1[i][j] = tree2[i][j] = 0;
for(int i = 1; i <= n; ++i) {
for(int j = a[i]; j; --j) {
int up = query2(a[i], j);
ans += up, ans %= mod;
update1(j, a[i], up), update2(a[i], j, up);
}
for(int j = n; j > a[i]; --j) {
int up = query1(a[i], j);
ans += up, ans %= mod;
update1(a[i], j, up), update2(j, a[i], up);
}
++ans, ans %= mod;
update1(1, a[i], 1), update2(a[i], 1, 1);
}
printf("%d\n", ans + 1);
}
return 0;
}