首页 > 其他分享 >P9744 「KDOI-06-S」消除序列 题解

P9744 「KDOI-06-S」消除序列 题解

时间:2023-10-25 11:56:06浏览次数:43  
标签:P9744 le 06 int 题解 sum3 sum2 sum1 500050

@

目录

Desciption

给定一个长度为 \(i\) 的序列 \(v_1,v_2,\dots,v_n\),初始时所有元素的值都为 \(1\)。

对于下标 \(i\) 有 \(3\) 种操作:

  • 将 \(v_1,v_2,\dots,v_i\) 的值变为 \(0\),费用是 \(a_i\)。
  • 将 \(v_i\) 的值变为 \(0\),费用是 \(b_i\)。
  • 将 \(v_i\) 的值变为 \(1\),费用是 \(c_i\)。

有 \(q\) 次询问,每次询问给定一个大小为 \(m\) 的集合 \(P\),问最少需要多少费用,使得 \(i\in P,v_i=1(1\le i\le n),j\notin P ,v_j=0(1\le j\le n)\)。

Solution

引理:在一次询问内,第一种操作最多只会进行一次。

设 \(i,j(i<j)\) 分别进行了一次操作一。

如果先在 \(j\) 进行操作一,就已经把 \(v1,\dots ,vi\) 变为 \(0\) 了,再操作是不优的。

所以遍历每一个 \(i\),发现在 \(i\) 做操作一时,答案为 \(a_i+\sum\limits_{j=i+1,j\notin P}^n b_j+\sum\limits_{j=1,j\in P}^{i} c_j\),这个式子可以用前缀和优化。

设 \(sum1_i=\sum\limits_{j=1}^i b_j(1\le i\le n),sum2_i=\sum\limits_{j=1}^mb_{P_j}(1\le i\le m),sum3_i=\sum\limits_{j=1}^m c_{P-j}(1\le i\le m)\)。

式子转换为 \(a_i+sum1_n-sum1_i-(sum2_m-sum2_j)+sum3_j(P_j\le i,P_{j+1}>i)\)。

此时时间复杂度为 \(O(qn)\),需要进一步优化。

发现对于在 \(P_i\) 和 \(P_{i+1}\) 之间操作操作一(不含两端),\(j\) 是相同的,所以我们只需预处理求出 \(g_k=a_k+sum1_n-sum1_k\),再处理出区间内 \(g\) 的最小值。可以用线段树或 ST表维护。

此时对于 \(i\),得出 \([P_i+1,P_{i+1}-1]\) 内 \(g\) 的最小值再加上式子中其他的值即可,\([P_m+1,n]\) 也要计算。

还要计算刚好在 \(i\) 上做操作一时的值,没有操作一时的值以及没有操作二时的值,所有可能答案取最小即可。

时间复杂度 \(O(qm)\)。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long  //记得开long long
int n,q;
int a[500050],b[500050],c[500050];
int p[500050];
int lg[500050],st[500050][22];
int sum1[500050],sum2[500050],sum3[500050];
int get_st(int l,int r){
	if(l>r) return 100000000000;
	int len=lg[r-l+1];
	return min(st[l][len],st[r-(1<<(len))+1][len]);
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=2;i<=n;i++){
		lg[i]=lg[i>>1]+1;
	}
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
		sum1[i]=sum1[i-1]+b[i];
	}
	for(int i=1;i<=n;i++){
		cin>>c[i];
		st[i][0]=sum1[n]-sum1[i]+a[i];  //得出g值
	}
	for(int j=1;j<=lg[n];j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);  //预处理ST表求区间内最小的g
		}
	}
	cin>>q;
	while(q--){
		int m;
		cin>>m;
		for(int i=1;i<=m;i++){
			cin>>p[i];
			sum2[i]=sum2[i-1]+b[p[i]];
			sum3[i]=sum3[i-1]+c[p[i]];
		}
		int ans=100000000000;  
		for(int i=1;i<=m;i++){
			ans=min(ans,min(get_st(p[i-1]+1,p[i]-1)-sum2[m]+sum2[i-1]+sum3[i-1],a[p[i]]+sum1[n]-sum1[p[i]]-(sum2[m]-sum2[i])+sum3[i]));  //min内第一个数是取区间,第二个数是刚好取pi
		}
		ans=min(ans,sum1[n]-sum2[m]);  //没有操作一
		ans=min(ans,get_st(p[m]+1,n)+sum3[m]);  //没有操作二
		cout<<ans<<endl;
	}
	return 0;
}

标签:P9744,le,06,int,题解,sum3,sum2,sum1,500050
From: https://www.cnblogs.com/larryyu/p/17786800.html

相关文章

  • Meta Hacker Cup 2023 Round 1 题解
    ProblemA:HereComesSantaClaus给一个数列,要求分成若干组,要求每组至少2个数,使得所有组中位数的最大值与最小值之差尽量大,求这个值。#include<bits/stdc++.h>usingnamespacestd;#defineFor(i,n)for(inti=1;i<=n;i++)#defineFork(i,k,n)for(inti=k;i<=n;i++)#define......
  • pytest运行警告问题解决:DeprecationWarning: pkg_resources is deprecated as an API
    前言最近在运行pytest的时候,经常出现这个警告DeprecationWarning:pkg_resourcesisdeprecatedasanAPISeehttps://setuptools.pypa.io/en/latest/pkg_resources.htmlfrompkg_resourcesimportiter_entry_points从警告上看是方法被弃用,肯定是因为新版弃用了旧版的语法。遇......
  • szfpga Lattice高速下载器HW-USBN-2B 常见问题解答
      .产品特点     1).支持windows7,Windows10操作系统,两个操作系统非常稳定不断线。  2).支持JTAG模式,速度快,最高30Mb/s,调试serdescore,不会像hw-usbn-2a出现错误。如这种错误Error:failedtosetcablepor(cable:USBport:EzUSB-0error:-1)  3). ......
  • CF1854E Games Bundles 题解
    乱搞题设个\(dp[i]\)表示和为\(i\)的子序列个数,那么转移是容易的,\(dp[j]+=dp[j-i]\),然后就判下\(dp[60]+dp[60-i]\)是否大于\(m\),发现这样子搞对于比较大的数可能达不到\(m\)的限制,因为这样子转移,默认的是一个数只选一次,但是我们可以重复选,这启发我们需要设定一个值......
  • 题解 CF903G【Yet Another Maxflow Problem】
    加边\(A_n\stackrel{0}{\to}A_{n+1}\),\(B_0\stackrel{0}{\to}B_1\)。称形如\(A_i\toA_{i+1}\)的边为左部边,形如\(B_j\toB_{j+1}\)的边为右部边,形如\(A_i\toB_j\)的边为中间边。根据最大流最小割定理,将最大流问题转化为最小割问题求解。显然,至少存在一组最小割,包含恰好......
  • CF1777D题解
    分析首先看到那个\(10^{100}\)再加上样例,我们就能意识到在不是特别多的操作次数后这颗树上的值就会全变成\(0\)。因为没有子节点在一次操作后显然就会变成\(0\),然后第一次叶节点就会变成\(0\),然后下一次子节点中只有叶节点的就会变成\(0\),以此类推,理论上最多操作\(n\)......
  • CF1878B题解
    CF1878BAleksaandStack题目翻译给定\(n\),试构造一个长度为\(n\)的严格上升正整数序列\(a_1,a_2,a_3,...,a_n\)使得\(\foralli\in[3,n],(a_{i-1}+a_{i-2})\nmid3a_i\)。单个测试点内包含多组测试数据。思路拿到题目,发现不好一个数一个数地构造,考虑......
  • 华科新生赛题解
    因为学校里面写代码的条件不足,比如教学楼里面使用键盘就会被盯着看。感觉有点点自闭。早知道退学了。不知道现在退学是不是算晚。昨天好兄弟车昱辉说你是在学习又不是在打游戏,但是我还是很羞涩。Abfs,需要把已经搜到的点在枚举1到n的时候去掉,所以可以使用并查集。或者链表......
  • CF1777C题解
    分析看到题面里面的子序列觉得很恶心,如果是子段感觉就会比较好做。如果直接填上子序列中间的空隙就可能会取一些比必须要取的数更大或者更小的数,影响我们的答案。那么就可以直接排序,使得子序列中间的空隙的数必然\(\geq\)左端且\(\leq\)右端,不会影响我们的答案(因为极差只......
  • [题解]CF1223F Stack Exterminable Arrays
    CCF出的原题观摩一下。思路首先可以用一个Trie来维护。在这里对本文中的一些变量做一下说明。\(p\)表示当前维护的Trie中,指向的元素编号。\(t_i\)表示在Trie中编号为\(i\)的元素在原序列中的值。\(f_i\)表示在Trie中编号为\(i\)的元素在Trie中的父......