[ICPC 2022 Nanjing R] 索道题解

题目描述

紫金山是南京的名山之一,而其中的紫金山索道曾是中国最长的吊椅式索道。游客们可以从山脚搭乘索道并一路直达山顶,总用时不超过十分钟。

旧紫金山索道。MiNe 摄。通过 CC BY 2.0 协议授权。

为了建设索道,除了山脚和山顶的索道站,还需要沿路架设支撑塔。工程师们已经在距离索道入口 0 单位距离和 (n+1) 单位距离的位置建设了索道站,并勘察了在 1,2,⋯,n 单位距离架设支撑塔的成本,分别是 a1​,a2​,⋯,an​。

出于工程因素考虑,部分位置必须架设支撑塔。同时为了保证索道的安全性,相邻支撑塔或索道站之间的距离必须小于等于 k。也就是说,假设最终建设两座索道站与架设 m 座支撑塔的位置为 b0​,b1​,b2​,⋯,bm​,bm+1​,其中 0≤m≤n,0=b0​<b1​<b2​<⋯<bm​<bm+1​=n+1,那么对于所有 1≤i≤m+1 有 bi​−bi−1​≤k。

同时,为了使建设方案更加灵活,工程师们会对成本序列进行 q 次临时的修改。第 i 次修改形如 (pi​,vi​),意思是临时将 api​​ 的值修改为 vi​。

您需要对每次修改求出,符合以上要求的前提下,架设支撑塔的最小总成本。

请再次注意,所有修改都是临时且相互独立的。也就是说,在计算一次修改的答案之后,此次修改将会被撤销,成本序列将会恢复原来的样子。

输入格式

有多组测试数据。第一行输入一个整数 T 表示测试数据组数,对于每组测试数据:

第一行输入两个整数 n 与 k(1≤n≤5×105,1≤k≤min(n+1,3×103))表示架设支撑塔的备选位置数以及相邻支撑塔或索道站之间的最大距离。

第二行输入 n 个整数 a1​,a2​,⋯,an​(1≤ai​≤109),其中 ai​ 表示在 i 单位距离架设支撑塔的成本。

第三行输入一个长度为 n 的二进制字符串 s1​s2​⋯sn​(si​∈{‘0’,‘1’})。如果 si​=‘1’ 则必须在 i 单位距离架设支撑塔。如果 si​=‘0’ 则您可以决定是否在 i 单位距离架设支撑塔。

第四行输入一个整数 q(1≤q≤3×103)表示修改的次数。

对于接下来 q 行,第 i 行输入两个整数 pi​ 与 vi​(1≤pi​≤n,1≤vi​≤109)表示第 i 次修改。

保证所有数据 n 之和不超过 2×106。另外保证所有数据 k 之和与 q 之和均不超过 104。

输出格式

每次修改输出一行一个整数表示临时应用该修改后,架设支撑塔的最小总成本。

输入输出样例

输入 #1复制

3
10 3
5 10 7 100 4 3 12 5 100 1
0001000010
2
2 3
6 15
5 6
1 1 1 1 1
00000
1
3 100
5 6
1 1 1 1 1
00100
1
3 100

输出 #1复制

206
214
0
100

说明/提示

对于第一组样例数据:

  • 应用第一次修改后,成本序列变为 {5,3,7,100,4,3,12,5,100,1}。应选择在 2,4,6 与 9 单位距离架设支撑塔以最小化总成本。
  • 应用第二次修改后,成本序列变为 {5,10,7,100,4,15,12,5,100,1}。应选择在 1,4,5,8 与 9 单位距离架设支撑塔以最小化总成本。

对于第二组样例数据,无需架设支撑塔。

对于第三组样例数据,必须在 3 单位距离架设支撑塔,因此答案就是 a3​。

思路

前后缀DP。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long t,n,k,a[500005],q,p,u,f[500005],dd[500005],dd2[500005],f2[500005],sc=0,lk=0,sd[500005],p2;
char s[500005];
deque<long long> de;
int main(){
    cin>>t;
    while(t--){
        memset(sd,62,sizeof(sd));
        memset(f,0,sizeof(f));
        memset(f2,0,sizeof(f2));
        cin>>n>>k;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            dd[i]=n;
            dd2[i]=1;
        }
        for(int i=1;i<=n;i++){
            cin>>s[i];
        }
        de.clear();
        for(int i=1;i<=n;i++){
            while(de.size()>=1&&f[i-1]<=f[de.back()]-1){
                de.pop_back();
            }
            de.push_back(i-1);
            while(de.size()>=1&&i-de[0]>=k+1){
                de.pop_front();
            }
            if(s[i-1]=='1'){
                de.clear();
                de.push_back(i-1);
            }
            f[i]=f[de[0]]+a[i];
        }
        de.clear();
        for(int i=n;i>=1;i--){
            while(de.size()>=1&&f2[i+1]<=f2[de.back()]-1){
                de.pop_back();
            }
            de.push_back(i+1);
            while(de.size()>=1&&de[0]-i>=k+1){
                de.pop_front();
            }
            if(s[i+1]=='1'){
                de.clear();
                de.push_back(i+1);
            }
            f2[i]=f2[de[0]]+a[i];
        }       
        s[0]=s[n+1]='1';
        cin>>q;
        for(int qss=1;qss<=q;qss++){
            cin>>p>>u;
            lk=f[p]+f2[p]-2*a[p]+u;
            if(s[p]=='0'){
                //cout<<lk<<endl;
                sd[p]=1e18+7;
                p2=p;
                for(int i=p-1;p-i<=k-1;i--){
                    sd[i]=min(sd[i+1],f[i]);
                    p2=i;
                    if(s[i]=='1'){
                        break;
                    }
                }
                for(int i=p+1;i-p<=k-1;i++){
                    lk=min(lk,f2[i]+sd[max(p2,i-k)]);
                    if(s[i]=='1'){
                        break;
                    }
                }
                for(int i=p-1;p-i<=k-1;i--){
                    sd[i]=1e18+7;
                    if(s[i]=='1'){
                        break;
                    }
                }
            }
            cout<<lk<<endl;
        }
    }
    return 0;
}

posted @ 2025-10-20 20:43  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源