题解 [PR #1] 删数
- 见到 先想想放到差分序列上有什么性质
自闭了,签到题不会做
考虑差分序列
那么每次就是选两个相邻且相等的 合并成
应当注意到的性质是这一过程只能重复 次
而且只有符号相同且 相等的 才能合并
那么可以据此将差分序列分为若干个连续段,每个连续段间是独立的
发现两个相等值相加等价于 ×2
那么问题转化为给定一个序列 a,,每次可以选两个相等的数 合并成 ,求最大合并次数
还是根据只能合并 log 次,一个 DP 是令 为右端点为 时,合并出 的左端点
令 为前 个位置的答案,那么可以利用 来转移
注意特殊处理差分序列中的 0
复杂度
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 300010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N], b[N], d[N], tag[N], f[N], g[N][35], pre[N], lg[N], tot, ans;
inline int lowbit(int i) {return i&-i;}
int solve() {
// cout<<"solve: "; for (int i=1; i<=tot; ++i) cout<<d[i]<<' '; cout<<endl;
for (int i=1; i<=tot; ++i) for (int j=0; j<=32; ++j) g[i][j]=0;
for (int i=1; i<=tot; ++i) pre[i]=pre[i-1]+(1<<d[i])-1, f[i]=0;
for (int i=1; i<=tot; ++i) {
g[i][d[i]]=i;
for (int j=d[i]+1; j<=32&&g[i][j-1]; ++j)
g[i][j]=g[g[i][j-1]-1][j-1];
for (int j=d[i]; j<=32&&g[i][j]; ++j)
f[i]=max(f[i], f[g[i][j]-1]+(1<<j)-1-pre[i]+pre[g[i][j]-1]);
f[i]=max(f[i], f[i-1]);
}
// cout<<g[2][1]<<endl;
// cout<<"f: "; for (int i=1; i<=tot; ++i) cout<<f[i]<<' '; cout<<endl;
return f[tot];
}
signed main()
{
int T=read();
while (T--) {
ans=n=read();
for (int i=1; i<=n; ++i) a[i]=read();
for (int i=2; i<=n; ++i) d[i]=a[i]-a[i-1];
// cout<<"d: "; for (int i=2; i<=n; ++i) cout<<d[i]<<' '; cout<<endl;
for (int i=2; i<=n; ++i)
if (d[i]) tag[i]=(d[i]<0?-1:1)*abs(d[i])/lowbit(abs(d[i]));
else tag[i]=0;
// cout<<"tag: "; for (int i=2; i<=n; ++i) cout<<tag[i]<<' '; cout<<endl;
int lst=2, min_tag;
for (int i=2; i<=n; ++i) {
if (tag[i]!=tag[lst]) {
tot=0; min_tag=INF;
for (int j=lst; j<i; ++j) min_tag=min(min_tag, abs(a[j]-a[j-1]));
if (!min_tag) ans-=max(0, i-lst-1);
else {
for (int j=lst; j<i; ++j) d[++tot]=__builtin_ctz(abs(a[j]-a[j-1])/min_tag);
ans-=solve();
}
lst=i;
}
}
tot=0; min_tag=INF;
for (int i=lst; i<=n; ++i) min_tag=min(min_tag, abs(a[i]-a[i-1]));
if (!min_tag) ans-=max(0, n-lst+1-1);
else {
for (int i=lst; i<=n; ++i) d[++tot]=__builtin_ctz(abs(a[i]-a[i-1])/min_tag);
ans-=solve();
}
printf("%d\n", ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?