正题

题目链接:https://www.luogu.com.cn/problem/CF573D


题目大意

给出\(n\)个人\(n\)匹马,每个人/马有能力值\(w_i\)/\(h_i\)。

第\(i\)个人开始对应第\(i\)匹马,每个人不能选择对应的马,给每个人分配一个马后求最大的\(\sum w_i\times h_j\)。

每次交换两个人对应的马后求答案。

\(1\leq n\leq 30000,1\leq q\leq 10000\)


解题思路

设\(f_i\)表示匹配完前\(i\)匹马时的最大价值和。

考虑怎么转移,因为人和马一一对应,正常来说大的对大的乘积的和最大。但是如果恰好第\(i\)个人对应了第\(i\)匹马,那么显然\(i\)只能选择\(i+1\),而让\(i+1\)选择\(i\)。

然后还有一种情况是只有三个时,第一个人对应了第一匹马,上面的转移会使得最后一个人和最后一匹马无法匹配,故我们还需要考虑和第三个的匹配。

也就是\(f_i\)只会从\(f_{i-1},f_{i-2},f_{i-3}\)转移过来,所以上动态\(dp\)即可

时间复杂度\(O(3^3n\log n )\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=31000,inf=1e18,S=3;
struct matrix{
ll a[S][S];
}w[N<<4],c,tt;
struct node{
ll p,w;
}e[N],h[N];
ll n,m,id[N];
matrix operator*(const matrix &a,const matrix &b){
memset(c.a,0xcf,sizeof(c.a));
for(ll i=0;i<S;i++)
for(ll j=0;j<S;j++)
for(ll k=0;k<S;k++)
c.a[i][j]=max(c.a[i][j],a.a[i][k]+b.a[k][j]);
return c;
}
bool cmp(node x,node y){return x.w>y.w;}
void Change(ll x,ll L,ll R,ll pos,matrix &val){
if(L==R){w[x]=val;return;}
ll mid=(L+R)>>1;
if(pos<=mid)Change(x*2,L,mid,pos,val);
else Change(x*2+1,mid+1,R,pos,val);
w[x]=w[x*2]*w[x*2+1];
}
ll calc(ll l,ll r){
if(l<=0)return -inf;
ll n=r-l+1,c[4]={0,1,2,0},ans=-inf;
do{
ll sum=0;
for(ll j=0;j<n;j++){
if(e[l+c[j]].p==h[l+j].p){sum=-inf;break;}
sum=sum+e[l+c[j]].w*h[l+j].w;
}
ans=max(ans,sum);
}while(next_permutation(c,c+n));
return ans;
}
void Updata(ll x){
if(x>n)return;
memset(tt.a,0xcf,sizeof(tt.a));
tt.a[1][0]=0;tt.a[2][1]=0;
tt.a[0][2]=calc(x-2,x);
tt.a[1][2]=calc(x-1,x);
tt.a[2][2]=calc(x,x);
Change(1,1,n,x,tt);return;
}
signed main()
{
scanf("%lld%lld",&n,&m);
// memset(tt.a,0xcf,sizeof(tt.a));
// tt.a[0][0]=tt.a[1][1]=tt.a[2][2]=0;
// for(ll i=1;i<(N<<2);i++)w[i]=tt[i];
for(ll i=1;i<=n;i++)scanf("%lld",&e[i].w),e[i].p=i;
for(ll i=1;i<=n;i++)scanf("%lld",&h[i].w),h[i].p=i;
sort(e+1,e+1+n,cmp);
sort(h+1,h+1+n,cmp);
for(ll i=1;i<=n;i++)id[e[i].p]=i;
for(ll i=1;i<=n;i++)Updata(i);
while(m--){
ll l,r;
scanf("%lld%lld",&l,&r);
l=id[l];r=id[r];
swap(e[l].p,e[r].p);
for(ll i=0;i<3;i++)
Updata(l+i),Updata(r+i);
printf("%lld\n",w[1].a[2][2]);
}
return 0;
}

CF573D-Bear and Cavalry【动态dp】的更多相关文章

  1. 【CF573D】Bear and Cavalry 线段树

    [CF573D]Bear and Cavalry 题意:有n个人和n匹马,第i个人对应第i匹马.第i个人能力值ai,第i匹马能力值bi,第i个人骑第j匹马的总能力值为ai*bj,整个军队的总能力值为$ ...

  2. 动态DP之全局平衡二叉树

    目录 前置知识 全局平衡二叉树 大致介绍 建图过程 修改过程 询问过程 时间复杂度的证明 板题 前置知识 在学习如何使用全局平衡二叉树之前,你首先要知道如何使用树链剖分解决动态DP问题.这里仅做一个简 ...

  3. Luogu P4643 【模板】动态dp

    题目链接 Luogu P4643 题解 猫锟在WC2018讲的黑科技--动态DP,就是一个画风正常的DP问题再加上一个动态修改操作,就像这道题一样.(这道题也是PPT中的例题) 动态DP的一个套路是把 ...

  4. 动态dp学习笔记

    我们经常会遇到一些问题,是一些dp的模型,但是加上了什么待修改强制在线之类的,十分毒瘤,如果能有一个模式化的东西解决这类问题就会非常好. 给定一棵n个点的树,点带点权. 有m次操作,每次操作给定x,y ...

  5. 洛谷P4719 动态dp

    动态DP其实挺简单一个东西. 把DP值的定义改成去掉重儿子之后的DP值. 重链上的答案就用线段树/lct维护,维护子段/矩阵都可以.其实本质上差不多... 修改的时候在log个线段树上修改.轻儿子所在 ...

  6. 动态 DP 学习笔记

    不得不承认,去年提高组 D2T3 对动态 DP 起到了良好的普及效果. 动态 DP 主要用于解决一类问题.这类问题一般原本都是较为简单的树上 DP 问题,但是被套上了丧心病狂的修改点权的操作.举个例子 ...

  7. 动态dp初探

    动态dp初探 动态区间最大子段和问题 给出长度为\(n\)的序列和\(m\)次操作,每次修改一个元素的值或查询区间的最大字段和(SP1714 GSS3). 设\(f[i]\)为以下标\(i\)结尾的最 ...

  8. [总结] 动态DP学习笔记

    学习了一下动态DP 问题的来源: 给定一棵 \(n\) 个节点的树,点有点权,有 \(m\) 次修改单点点权的操作,回答每次操作之后的最大带权独立集大小. 首先一个显然的 \(O(nm)\) 的做法就 ...

  9. UOJ268 [清华集训2016] 数据交互 【动态DP】【堆】【树链剖分】【线段树】

    题目分析: 不难发现可以用动态DP做. 题目相当于是要我求一条路径,所有与路径有交的链的代价加入进去,要求代价最大. 我们把链的代价分成两个部分:一部分将代价加入$LCA$之中,用$g$数组保存:另一 ...

随机推荐

  1. Azkaban入门(启动一个Simple Example)

    Azkaban简介 azkaban是一个开源的任务调度系统 Azkaban是一套简单的任务调度服务,整体包括三部分webserver.dbserver.executorserver. 开发语言为Jav ...

  2. qt work

    auto folder1="./.mm"; QDir *folder = new QDir; bool exist = folder->exists(folder1); if ...

  3. springCloud之路API路由网关Zuul

    1.简介 简单的理解就是,相当于在所有服务的调用前加了一层防火墙, 主要就是对外提供服务接口的时候,起到了请求的路由和过滤作用,也因此能够隐藏内部服务的接口细节,提高系统的安全性: 官方文档:http ...

  4. 【权限管理】springboot集成security

    摘自: https://www.cnblogs.com/hhhshct/p/9726378.html https://blog.csdn.net/weixin_42849689/article/det ...

  5. C# 委托讲解

    首先,委托的使用场景:A的某些功能,只有在B需要触发时触发,委托就是用来做中间通讯的渠道. 假设:现在有个大佬A,A有个小弟B,B在受到羞辱时就会通过电话Delegate通知A自己被羞辱了,A在这时就 ...

  6. mysql基础操作(一):DDL、DML

    -- 1.在命令行中开启数据库: net start mysql -- 2.在命令行中关闭数据库: net stop mysql 1.DDL语句:create.drop.alter -- 查看所有的数 ...

  7. UVA1620 Lazy Susan(结论证明)

    结论: 当 \(n\geq 6\) 时,若 \(n\) 是奇数且输入序列的逆序对数是奇数,则无解,否则有解. 当 \(n=4\) 或 \(n=5\) 时,答案个数及其有限,只有这个环是 \(1\) 到 ...

  8. deepin-terminal改造风云再起

    1. 创作背景 使用deepin-terminal的时候,我发现一些小的问题. 在论坛的帖子(https://bbs.deepin.org/zh/post/224502)也总结反馈了这些问题 终端标签 ...

  9. vue3.0入门(四):组件

    组件 组件基础 <my-counter></my-counter> const app = Vue.createApp({ // 根组件 data() { return {} ...

  10. Ubuntu16.04 Linux 下安装、配置SSH

    本人在Win7+VMware下利用两个ubuntu虚拟机安装.配置.测试了SSH. 在Server端安装openssh-server. sudo apt-get install ssh # 安装ssh ...