CF573D Bear and Cavalry
比较简单的
看见题目的
-
若
对应的编号不相等,肯定是把它们配对。 -
若
对应的编号相等,考虑这样的连法:
-
若是这种情况也不合法,或者它们之后又有一个点不合法,我们再加一个点,会得到两种情况:
而这样一定可以得到最优,之后不合法的规模继续扩大,我们也可以拆分成上述的小问题。
所以转移方程易得:
从大往小进行转移,转移前注意判断是否合法,时间复杂度
但是这个方程明显支持矩阵优化,我们列出转移矩阵,用线段树维护即可。
我们用广义矩阵乘法:
注意线段树
#include<bits/stdc++.h>
using namespace std;
#define rd read()
#define ll long long
#define in inline
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define ROF(i,j,k) for(int i=j;i>=k;i--)
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
const int N=1e5+10;
const ll INF=1e17;
int n,q,w[N],h[N],idw[N],idh[N],dw[N],dh[N],tmp[N];
bool cmp(int a,int b){return tmp[a]<tmp[b];}
struct matrix{
ll a[3][3];
matrix(){memset(a,0,sizeof(a));}
matrix operator*(matrix const&T){
matrix res;
FOR(i,0,2) FOR(j,0,2) res.a[i][j]=-INF;
FOR(i,0,2){
FOR(k,0,2){
ll r=a[i][k];
FOR(j,0,2) res.a[i][j]=max(res.a[i][j],r+T.a[k][j]);
}
}
return res;
}
}g[N],tr[N<<2];
void pushup(int u){tr[u]=tr[u<<1|1]*tr[u<<1];}
void build(int u,int l,int r){
if(l==r){tr[u]=g[l];return;}
int mid=(l+r)>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,int x){
if(l==r){tr[u]=g[l];return;}
int mid=(l+r)>>1;
if(x<=mid) modify(u<<1,l,mid,x);
else modify(u<<1|1,mid+1,r,x);
pushup(u);
}
void init(int x){
if(idw[x]!=idh[x]) g[x].a[0][0]=1ll*w[x]*h[x];
else g[x].a[0][0]=-INF;
if(x>1) g[x].a[0][1]=(idw[x]!=idh[x-1]&&idw[x-1]!=idh[x])?1ll*w[x]*h[x-1]+1ll*w[x-1]*h[x]:-INF;
else g[x].a[0][1]=-INF;
if(x>2){
bool flag=false;ll res=-INF;
if(idw[x]!=idh[x-1]&&idw[x-1]!=idh[x-2]&&idw[x-2]!=idh[x])
flag=true,res=max(res,1ll*w[x]*h[x-1]+1ll*w[x-1]*h[x-2]+1ll*w[x-2]*h[x]);
if(idw[x]!=idh[x-2]&&idw[x-1]!=idh[x]&&idw[x-2]!=idh[x-1])
flag=true,res=max(res,1ll*w[x]*h[x-2]+1ll*w[x-1]*h[x]+1ll*w[x-2]*h[x-1]);
g[x].a[0][2]=res;
}
else g[x].a[0][2]=-INF;
g[x].a[1][0]=g[x].a[2][1]=0,g[x].a[1][1]=g[x].a[1][2]=g[x].a[2][0]=g[x].a[2][2]=-INF;
}
int main(){
n=rd,q=rd;
FOR(i,1,n) w[i]=rd,idw[i]=i,tmp[i]=w[i];
sort(idw+1,idw+1+n,cmp);
FOR(i,1,n) w[i]=tmp[idw[i]];
FOR(i,1,n) h[i]=rd,idh[i]=i,tmp[i]=h[i];
sort(idh+1,idh+1+n,cmp);
FOR(i,1,n) h[i]=tmp[idh[i]];
FOR(i,1,n) dw[idw[i]]=i,dh[idh[i]]=i;
FOR(i,1,n) init(i);
build(1,1,n);
while(q--){
int x=rd,y=rd;
swap(dh[x],dh[y]),swap(idh[dh[x]],idh[dh[y]]);
FOR(i,dh[x],min(n,dh[x]+2)) init(i),modify(1,1,n,i);
FOR(i,dh[y],min(n,dh[y]+2)) init(i),modify(1,1,n,i);
printf("%lld\n",tr[1].a[0][0]);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现