CF1215题解
2024-08-23 03:24:55
E
假设从小到大排序,每次交换相邻两个,最小次数即冒泡排序也就是逆序对
考虑值域较小,把每个值映射到\([1,20]\)
设\(f_i\)为已经加入集合为\(i\)的值的最小逆序对个数,考虑填表法
即枚举每个在i里的数x,考虑其为最后加进来的数
再枚举其他的数y,考虑在原序列中形似(x,y)的个数,这个很容易预处理出来
#include<bits/stdc++.h>
typedef long long LL;
const LL maxn=1e6+9,inf=0x3f3f3f3f3f3f3f3f;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<3)+(x<<1)+c-'0'; c=getchar();
}return x*f;
}
LL n;
LL a[maxn],cnt[29],f[1<<21],sum[29][29];
int main(){
n=Read();
for(LL i=1;i<=n;++i){
a[i]=Read();
++cnt[a[i]];
for(LL j=1;j<=20;++j){
if(j==a[i]) continue;
sum[j][a[i]]+=cnt[j];
}
}
memset(f,inf,sizeof(f));
f[0]=0;
LL up=1<<20;
for(LL i=1;i<up;++i){
for(LL j=1;j<=20;++j){
if(!((1<<j-1)&i)) continue;
LL nw(0);
LL pre(i-(1<<j-1));
for(LL k=1;k<=20;++k){
if(k==j) continue;
if(!((1<<k-1)&i)) continue;
nw+=sum[j][k];
}
f[i]=std::min(f[i],f[pre]+nw);
}
}
printf("%lld\n",f[up-1]);
return 0;
}
F
挖个坑,顺便奶一口CSP考2-sat
最新文章
- Logistic回归的使用
- SharePoint 2013 表单认证使用ASP.Net配置工具添加用户
- 关于adb驱动
- linux进程调度方法(SCHED_OTHER,SCHED_FIFO,SCHED_RR)
- 微信小程序视频地址
- javascript 柯里化
- NSS_03 过滤器
- python logging 日志轮转文件不删除问题
- Linux串口编程详解(转)
- LNMP搭建02 -- 编译安装Nginx
- 解决win10 VC++6.0 应用程序无法正常运行 0xc0000142
- 在vue中关于element UI 中表格实现下载功能,表头添加按钮,和点击事件失效的解决办法。
- Pycharm问题:module &#39;pip&#39; has no attribute &#39;main&#39;
- HTML5 页面编辑API之Range对象
- Int和String互转的方法
- windows系统下简单nodejs安装及环境配置
- centos7如何安装部署Zabbix
- Golang GC原理
- Python sys.argv[] 的用法
- 3.3 线程---Handler消息传递机制浅析