D2. Hot Start Up (hard version)
D2. Hot Start Up (hard version)
思路
有两种方法:
1.求最小不相交的区间的和,但是需要偏移一下,这样才能保证区间一定不相交
2.根据D1中dp的式子中可以看出,只有1个点是进行了多次更新,其他的都是直接在原来的基础上进行加上对应的值。
代码1
/* 对于连续出现的数,直接将他减少的值加上就可以了 因为有两个cpu,所以可以看成一个是一直在工作,另外一个是用来等待的 处理一下是否需要等待这个数就可以了 也就是最大不相交区间问题 1 2 1 2 但是区间可能会出现相交的情况,但是最多只会重复一个点,所以将区间的右端点进行移动一下就可以了 */ #include <bits/stdc++.h> using namespace std; const int M = 3e5 + 5; #define endl '\n' #define int long long using pii = pair<int, int>; int a[M],b[M],cold[M],hot[M]; int dp[M],pre[M],w[M]; void solve() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=m;i++)cin>>cold[i],b[i]=0; for(int i=1;i<=m;i++)cin>>hot[i]; int sum=0; for(int i=1;i<=n;i++) { pre[i]=-1; sum+=(a[i]==a[i-1])?hot[a[i]]:cold[a[i]]; if(b[a[i]]&&a[i]!=a[i-1]) { pre[i-1]=b[a[i]]; w[i-1]=cold[a[i]]-hot[a[i]];//为什么是存在上一个位置呢 } b[a[i]]=i; } for(int i=1;i<=n;i++) { dp[i]=dp[i-1]; if(pre[i]!=-1)dp[i]=max(dp[i],dp[pre[i]]+w[i]); } cout<<sum-dp[n]<<endl; } signed main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int TT; cin >> TT; while(TT--) { solve(); } return 0; }
代码2
/* 由d1可知道,f(i,j)全部都是直接由f(i,j-1)直接转移过来的 只有上一个选择接在j后面,也就是保留a[i-1]的,才是在所有的里面取出一个最小值 所以可以由线段树来进行维护dp的变化 */ #include <bits/stdc++.h> using namespace std; const int M = 3e5 + 5; #define endl '\n' #define int long long const int inf = 1e18; #define mn(u) tr[u].mn #define la(u) tr[u].la #define ul u<<1 #define ur u<<1|1 struct node { int l,r,la,mn; }tr[M<<2]; void pu(int u) { mn(u)=min(mn(ul),mn(ur)); } void build(int u,int l,int r) { tr[u]={l,r,0,inf}; if(l==r)return ; int mid=(l+r)/2; build(ul,l,mid); build(ur,mid+1,r); } void pd(int u) { if(la(u)==0)return; la(ul)+=la(u); la(ur)+=la(u); mn(ul)+=la(u); mn(ur)+=la(u); la(u)=0; } int query(int u,int l,int r) { if(tr[u].l>=l&&tr[u].r<=r)return mn(u); if(tr[u].l>r||tr[u].r<l)return inf; pd(u); return min(query(ul,l,r),query(ur,l,r)); } void add(int u,int l,int r,int v) { if(tr[u].l>=l&&tr[u].r<=r) { la(u)+=v; mn(u)+=v; return; } if(tr[u].l>r||tr[u].r<l)return; pd(u); add(ul,l,r,v); add(ur,l,r,v); pu(u); } void up(int u,int pos,int v) { if(tr[u].l==tr[u].r&&tr[u].l==pos) { mn(u)=min(mn(u),v); return ; } if(tr[u].l>pos||tr[u].r<pos)return; pd(u); up(ul,pos,v); up(ur,pos,v); pu(u); } int a[M],w1[M],w2[M]; void solve() { int n,m; cin>>n>>m; build(1,0,m); up(1,0,0);//先将0这个点置为0 for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=m;i++)cin>>w1[i]; for(int i=1;i<=m;i++)cin>>w2[i]; for(int i=1;i<=n;i++) { int tmp=min(query(1,0,m)+w1[a[i]],query(1,a[i],a[i])+w2[a[i]]);//所有的点查询是不受影响的 //cout<<query(1,a[i-1],a[i-1])<<endl; add(1,0,m,a[i]==a[i-1]?w2[a[i]]:w1[a[i]]);//对所有的人进行更新就可以了 up(1,a[i-1],tmp);//然后对这个点进行单独的更新 } cout<<query(1,0,m)<<endl; } signed main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int TT; cin >> TT; while(TT--) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!