P7650 [BalticOI 2007 Day 1] Ranklist Sorting(DP)
容易发现一条性质:每个人最多只会被移动一次。说明人只有两种:移动的和不移动的。
考虑枚举所有不移动的人,并最优化其它人的移动顺序。最开始第
尝试用动态规划优化掉指数。从前往后扫不太可行,考虑以值域为阶段。此时上面提到的第二种贪心就派上用场了,因为终点位置和值域有关,所以依照上面的贪心,可以考虑从
定义
接下来我们讨论如何将贡献在状态转移
若权值为
若权值为
综上,不难得到转移方程:
,其中 表示 。 。
直接转移即可,时间复杂度
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define db double
#define ldb long double
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define FR first
#define SE second
using namespace std;
inline int read() {
int x = 0; bool op = 0;
char c = getchar();
while(!isdigit(c))op |= (c == '-'), c = getchar();
while(isdigit(c))x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return op ? -x : x;
}
const int N = 1e3 + 10;
const int INF = 1e9;
int n;
int a[N], f[N][N], p[N], pos[N], nxt[N], inc[N];
bool chkmin(int &a, int b) {return (b < a ? a = b, true : false);}
vector<pii> st;
void dfs(int cur, int now) {
if(cur > n)return ;
if(now != pos[cur]) {
dfs(cur + 1, now);
int p1 = 1, p2 = 1;
for(int i = 1; i < pos[cur]; i++)p1 += (p[i] < cur);
for(int i = 1; i <= now; i++)p2 += (p[i] < cur);
st.pb(mp(p1 + inc[cur], p2));
}
else {
dfs(cur + 1, nxt[cur]);
for(int i = pos[cur] + 1; i < nxt[cur]; i++) {
if(p[i] < cur)inc[p[i]] += cur - p[i];
}
}
return ;
}
int main() {
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
n = read();
for(int i = 1; i <= n; i++)a[i] = read();
for(int i = 1; i <= n; i++)pos[i] = i;
sort(pos + 1, pos + 1 + n, [&](int x, int y) {
return a[x] > a[y];
});
for(int i = 1; i <= n; i++)p[pos[i]] = i;
memset(f, 0x3f, sizeof(f));
p[n + 1] = n + 1; pos[n + 1] = n + 1; f[n + 1][n + 1] = 0;
for(int i = n; i; i--) {
int p1 = 1, p2 = 1;
for(int j = 1; j < pos[i]; j++)p1 += (p[j] < i);
for(int j = 1; j <= n + 1; j++) {
p2 += (p[j] < i);
chkmin(f[i][j], f[i + 1][j] + p1 + p2);
}
int sum = 0;
for(int j = pos[i] + 1; j <= n + 1; j++) {
if(chkmin(f[i][pos[i]], f[i + 1][j] + sum))nxt[i] = j;
sum += max(0, i - p[j]);
}
}
int ans = INF, now = 0;
for(int i = 1; i <= n + 1; i++) {
if(chkmin(ans, f[1][i]))now = i;
}
dfs(1, now);
printf("%d\n", st.size());
for(auto x : st)printf("%d %d\n", x.FR, x.SE);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通