当前位置: 首页 > news >正文

2025.11.19 D 题解

好题好题,但是这个音标题目名还是太生艹了。


第一眼感觉很多,感觉能柯朵莉树,但是有专门卡的包。后来发现似乎是得 \(dp\) 一下再找性质,但是没 \(dp\) 出来。

考虑性质:

每个数只会被换一次。
证明:假如换两次,来回换肯定不优,向前/向后换没有本质区别,那么就剩下下述情况(一点解释:为什么 \(x\) 前面都是 \(y\) 呢?因为不是 \(y\) 劣得没边):
1. \(y,x,y,z\),将 \(x\) 向后换两次。换一次都不优。
2. \(y,x,y,x\),将 \(x\) 向后换两次。换两次显然不优。
3. \(y,x,y,y\),将 \(x\) 向后换两次。换两次显然不优。
\(Q.E.D.\)(略显草率)

那就很好 \(dp\) 了。设 \(f_{i,0/1}\) 表示第 \(i\) 个位置有没有和前一个位置交换,则有:

\[f_{i,0}=\min(f_{i-1,0}+[a_i\ne a_{i-1}],f_{i-1,1}+[a_i\ne a_{i-2}]) \]

\[f_{i,1}=\min(f_{i-2,0}+[a_i\ne a_{i-2}],f_{i-2,1}+[a_i\ne a_{i-3}])+[a_i\ne a_{i-1}]+1 \]

发现这个东西可以用 \(O(4^3)\) 矩阵乘法优化,考虑动态 \(dp\)。发现区间加只会改变 \(l,l+1,l+2,r+1,r+2,r+3\) 六个位置的矩阵;区间推平除了改变这六个位置,还会将 \([l+3,r]\) 内的矩阵修改成一模一样的,区间修改+打标记即可。由于 \(a_i\) 会动态变化,所以还需要用一个线段树记录当前的 \(a_i\)

时间复杂度 \(O(4^3q\log n)\)。注意前三个位置实际上无法用常规的矩阵表示,所以先大力 \(dp\) 出来这三个位置再说。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,q,a[N],dp[5][2],zb;
int num[N<<2],tag[N<<2];
inline void buildd(int x,int l,int r){tag[x]=-1;if(l==r){num[x]=a[l];return;}int mid=(l+r)>>1;buildd(x<<1,l,mid);buildd(x<<1|1,mid+1,r);
}inline void downn(int x,int v){if(~tag[x]) tag[x]+=v;num[x]+=v;
}inline void downt(int x,int v){num[x]=tag[x]=v;}
inline void pushdown(int x){if(~tag[x]) downt(x<<1,tag[x]),downt(x<<1|1,tag[x]),tag[x]=-1;else downn(x<<1,num[x]),downn(x<<1|1,num[x]);num[x]=0;
}inline void add(int x,int l,int r,int L,int R,int v){if(L<=l&&r<=R) return downn(x,v);int mid=(l+r)>>1;pushdown(x);if(L<=mid) add(x<<1,l,mid,L,R,v);if(R>mid) add(x<<1|1,mid+1,r,L,R,v);
}inline void assign(int x,int l,int r,int L,int R,int v){if(L<=l&&r<=R) return downt(x,v);int mid=(l+r)>>1;pushdown(x);if(L<=mid) assign(x<<1,l,mid,L,R,v);if(R>mid) assign(x<<1|1,mid+1,r,L,R,v);
}inline int find(int x,int l,int r,int k){if(l==r) return num[x];int mid=(l+r)>>1;pushdown(x);if(k<=mid) return find(x<<1,l,mid,k);return find(x<<1|1,mid+1,r,k);
}inline int fd(int x){return x>=zb?find(1,1,n,x):-1;}
inline void solve(int l,int r){dp[0][0]=0,dp[0][1]=1e9,zb=l;for(int i=1;i+l-1<=r;i++){dp[i][0]=dp[i-1][0]+(fd(i+l-1)!=fd(i+l-2)),dp[i][1]=1e9;if(i>1) dp[i][0]=min(dp[i][0],dp[i-1][1]+(fd(i+l-1)!=fd(i+l-3)));if(i>2) dp[i][1]=dp[i-2][0]+(fd(i+l-1)!=fd(i+l-2))+(fd(i+l-1)!=fd(i+l-3))+1;if(i>3) dp[i][1]=min(dp[i][1],dp[i-2][1]+(fd(i+l-1)!=fd(i+l-2))+(fd(i+l-1)!=fd(i+l-4))+1);}
}struct matrix{int z[4][4];}sg[N<<2],zt[N],cc;int tg[N<<2];
inline matrix operator*(matrix x,matrix y){matrix z;memset(z.z,0x3f,sizeof(z.z));for(int i=0;i<4;i++) for(int j=0;j<4;j++)for(int k=0;k<4;k++) z.z[i][k]=min(z.z[i][k],x.z[i][j]+y.z[j][k]);return z;
}inline void gets(int id,int x){memset(sg[x].z,0x3f,sizeof(sg[x].z)),zb=0;int lsz=fd(id),lso=fd(id-1),lst=fd(id-2),lsh=fd(id-3);sg[x].z[0][0]=(lso!=lsz),sg[x].z[1][0]=(lst!=lsz);sg[x].z[2][1]=(lso!=lsz)+(lst!=lsz)+1,sg[x].z[0][2]=0;sg[x].z[3][1]=(lso!=lsz)+(lsh!=lsz)+1,sg[x].z[1][3]=0;
}inline void build(int x,int l,int r){if(l==r) return gets(l,x);int mid=(l+r)>>1;build(x<<1|1,mid+1,r);build(x<<1,l,mid),sg[x]=sg[x<<1]*sg[x<<1|1];
}inline void down(int x,int l,int r){tg[x]=1;sg[x]=zt[r-l];} 
inline void push_down(int x,int l,int r,int mid){if(tg[x]) down(x<<1,l,mid),down(x<<1|1,mid+1,r),tg[x]=0; 
}inline void ass(int x,int l,int r,int L,int R){if(L<=l&&r<=R) return down(x,l,r);int mid=(l+r)>>1;push_down(x,l,r,mid);if(L<=mid) ass(x<<1,l,mid,L,R);if(R>mid) ass(x<<1|1,mid+1,r,L,R);sg[x]=sg[x<<1]*sg[x<<1|1];
}inline void chg(int x,int l,int r,int k){if(k<4||k>n) return;if(l==r) return gets(l,x);int mid=(l+r)>>1;push_down(x,l,r,mid);if(k<=mid) chg(x<<1,l,mid,k);else chg(x<<1|1,mid+1,r,k);sg[x]=sg[x<<1]*sg[x<<1|1]; 
}inline void sum(int x,int l,int r,int L,int R,matrix &mt){if(L<=l&&r<=R){mt=mt*sg[x];return;}int mid=(l+r)>>1;push_down(x,l,r,mid);if(L<=mid) sum(x<<1,l,mid,L,R,mt);if(R>mid) sum(x<<1|1,mid+1,r,L,R,mt);
}int main(){freopen("swap.in","r",stdin);freopen("swap.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);cin>>n>>q,dp[0][0]=0,dp[0][1]=1e9,a[0]=-1;for(int i=1;i<=n;i++) cin>>a[i];buildd(1,1,n);if(n>3) build(1,4,n);memset(zt[0].z,0x3f,sizeof(zt[0].z));zt[0].z[0][0]=zt[0].z[1][0]=0;zt[0].z[2][1]=zt[0].z[3][1]=1;zt[0].z[1][3]=zt[0].z[0][2]=0;for(int i=1;i<=n;i++) zt[i]=zt[i-1]*zt[0];memset(cc.z,0x3f,sizeof(cc.z));while(q--){int op,l,r,v;cin>>op>>l>>r;if(op==1){cin>>v,add(1,1,n,l,r,v);chg(1,4,n,l),chg(1,4,n,l+1),chg(1,4,n,l+2);chg(1,4,n,r+1),chg(1,4,n,r+2),chg(1,4,n,r+3);}else if(op==2){cin>>v,assign(1,1,n,l,r,v);if(r-l>=3) ass(1,4,n,l+3,r);chg(1,4,n,l),chg(1,4,n,l+1),chg(1,4,n,l+2);chg(1,4,n,r+1),chg(1,4,n,r+2),chg(1,4,n,r+3);}else{if(r-l>2){solve(l,l+2),cc.z[0][0]=dp[3][0],cc.z[0][1]=dp[3][1];cc.z[0][2]=dp[2][0],cc.z[0][3]=dp[2][1],sum(1,4,n,l+3,r,cc);cout<<min(cc.z[0][0],cc.z[0][1])<<"\n";}else solve(l,r),cout<<min(dp[r-l+1][0],dp[r-l+1][1])<<"\n";}}return 0;
}
http://www.jsqmd.com/news/45981/

相关文章:

  • P11626 [迷宫寻路 Round 3] 七连击 分析
  • 芯谷科技--高性能电动工具直流调速电路GS069 - 指南
  • 【个人成长笔记】在本地Windows系统中如何正确使用adb pull命令,把Linux环境中的记录或文件夹复制到本地中(亲测有效)
  • 钩子
  • IOI 2026 中国国家集训队作业(试题泛做)记录
  • 洛谷 B4411:[GESP202509 二级] 优美的数字 ← 嵌套循环
  • 2025年门窗十大品牌专业选购手册:行业评估报告 + 白皮书指引,选窗更安心!
  • 文字识别系统
  • 2025 门窗十大品牌精准选购指南:行业评估报告 + 白皮书护航,选窗不踩坑!
  • 写的都对_第二次软件工程作业
  • 深入解析:spark组件-spark core(批处理)-rdd血缘
  • 深入解析:开源 Linux 服务器与中间件(十二)FRP内网穿透应用
  • CF1542E1 Abnormal Permutation Pairs (easy version)
  • 网络流建模
  • 实用指南:GLM 智能助力・Trae 跨端个人任务清单
  • AT_agc050 总结
  • 补 二分法与图
  • SpringSecurity 集成 CAS Client 处理单点登录 - Higurashi
  • NOIP2025模拟赛12(炼石计划NOIP模拟赛第 19 套题目)
  • [nanoGPT] GPT模型架构 | `LayerNorm` | `CausalSelfAttention` |`MLP` | `Block` - 实践
  • duckdb索引介绍
  • 25.11.20 最长不升序列LNIS和最长升序列LIS
  • 周赛提高组(栈与队列)
  • 2025.11.20 B 题解
  • 重组干扰素蛋白的结构特点与分子性质综述
  • 2025 门窗十大品牌权威榜单:依托行业评估报告 + 选购白皮书,省心采购指南!
  • 实用指南:OpenCV下载安装教程(非常详细)从零基础入门到精通,看完这一篇就够了(附安装包)
  • 详解 DPO
  • 程序员手记
  • Object.entries() 和 Object.formEntries()的用法详解