God knows(李超线段树\CDQ分治)

在这里插入图片描述 n < = 2 e 5 n<=2e5 n<=2e5

f i f_i fi为删除 ( i , p i ) (i,p_i) (i,pi)的线段并使得不存在线段 ( a , b ) , a < i , b < p i (a,b),a<i,b<p_i (a,b),a<i,b<pi的最少花费。
那么容易发现可以转移到 f i f_i fi f j f_j fj一定满足 p j p_j pj k = i − 1 , i − 2.... j k=i-1,i-2....j k=i1,i2....j中最大的满足 p k < p i p_k<p_i pk<pi p k p_k pk
也就是说在 k = i − 1 , i − 2....1 k=i-1,i-2....1 k=i1,i2....1且满足 p k < p i p_k<p_i pk<pi这个序列中
j j j是前缀最大值。
那么我们的问题就转化为了求前缀最大值的所有位置 j j j上的 f j f_j fj的最小值。
那么先从 i = 1 , 2.... n i=1,2....n i=1,2....n的顺序插入 ( i , p i ) (i,p_i) (i,pi),用一个李超线段树维护 p k < p i p_k<p_i pk<pi k k k所形成的序列的前缀最大值的位置上的 f f f的最小值。
解法类似于楼房重建

A C   C o d e \rm AC\ Code AC Code

#include<bits/stdc++.h>
#define maxn 200005
#define inf 0x7f7f7f7f
#define lc u<<1
#define rc u<<1|1
using namespace std;

int n,p[maxn],c[maxn],f[maxn];
struct data{
	int a,c;
	data(int a=0,int c=inf):a(a),c(c){}
	data operator +(const data &B)const{ return B.a<=0?*this:data(B.a,min(B.c,c)); }
}s[maxn<<2],sl[maxn<<2];
data cal(int u,int l,int r,int h){
	if(l==r) return s[u].a>h?s[u]:data();
	int mid = (l+r) >> 1;
	if(s[rc].a>h) return cal(rc,mid+1,r,h)+sl[u];
	return cal(lc,l,mid,h);
}
void upd(int u,int l,int r){ s[u] = s[rc] + (sl[u] = cal(lc,l,(l+r)>>1,s[rc].a)); }
void Insert(int u,int l,int r,int p,data v){
	if(l==r){ s[u]=v;return; }
	int mid = (l+r) >> 1;
	if(p <= mid) Insert(lc,l,mid,p,v);
	else Insert(rc,mid+1,r,p,v);
	upd(u,l,r);
}
data d;
void Query(int u,int l,int r,int ql,int qr){
	if(ql>qr) return;
	if(ql<=l&&r<=qr){ d=d+cal(u,l,r,d.a); return;}
	int mid = (l+r) >> 1;
	if(qr>mid) Query(rc,mid+1,r,max(ql,mid+1),qr);
	if(ql<=mid) Query(lc,l,mid,ql,min(mid,qr));
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&p[i]);
	for(int i=1;i<=n;i++) scanf("%d",&c[i]),f[i]=inf;
	f[1]=c[1],Insert(1,1,n,p[1],data(1,f[1]));
	for(int i=2;i<=n;i++){
		d=data();Query(1,1,n,1,p[i]-1);
		int t = d.c;if(t >= inf) t = 0;
		Insert(1,1,n,p[i],data(i,f[i]=min(f[i],t+c[i])));
	}
	d=data();Query(1,1,n,1,n);
	printf("%d\n",d.c);
}

考场上写的 C D Q \rm CDQ CDQ分治+ z k w \rm zkw zkw线段树。
主要就是按第一维分治求左半对右半的贡献,
按第二维 p p p从小到大枚举,左半能贡献的只有 p i < = p_i<= pi<=当前枚举的 p p p的所有 i i i中的后缀最大值,用线段树维护给右边,右边每一个点能接受的区间要看他前一个前缀最大值,故左右都需要用单调栈维护。

A C   C o d e \rm AC \ Code AC Code

#include<bits/stdc++.h>
#define maxn 200005
#define inf 0x7f7f7f7f
#define lc u<<1
#define rc u<<1|1
using namespace std;

int n,p[maxn],c[maxn],f[maxn];
struct data{
	int a,c;
	data(int a=0,int c=inf):a(a),c(c){}
	data operator +(const data &B)const{ return B.a<=0?*this:data(B.a,min(B.c,c)); }
}s[maxn<<2],sl[maxn<<2];
data cal(int u,int l,int r,int h){
	if(l==r) return s[u].a>h?s[u]:data();
	int mid = (l+r) >> 1;
	if(s[rc].a>h) return cal(rc,mid+1,r,h)+sl[u];
	return cal(lc,l,mid,h);
}
void upd(int u,int l,int r){ s[u] = s[rc] + (sl[u] = cal(lc,l,(l+r)>>1,s[rc].a)); }
void Insert(int u,int l,int r,int p,data v){
	if(l==r){ s[u]=v;return; }
	int mid = (l+r) >> 1;
	if(p <= mid) Insert(lc,l,mid,p,v);
	else Insert(rc,mid+1,r,p,v);
	upd(u,l,r);
}
data d;
void Query(int u,int l,int r,int ql,int qr){
	if(ql>qr) return;
	if(ql<=l&&r<=qr){ d=d+cal(u,l,r,d.a); return;}
	int mid = (l+r) >> 1;
	if(qr>mid) Query(rc,mid+1,r,max(ql,mid+1),qr);
	if(ql<=mid) Query(lc,l,mid,ql,min(mid,qr));
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&p[i]);
	for(int i=1;i<=n;i++) scanf("%d",&c[i]),f[i]=inf;
	f[1]=c[1],Insert(1,1,n,p[1],data(1,f[1]));
	for(int i=2;i<=n;i++){
		d=data();Query(1,1,n,1,p[i]-1);
		int t = d.c;if(t >= inf) t = 0;
		Insert(1,1,n,p[i],data(i,f[i]=min(f[i],t+c[i])));
	}
	d=data();Query(1,1,n,1,n);
	printf("%d\n",d.c);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用和提到,Linux下安装ffmpeg是非常方便的。下面给出在Linux上安装ffmpeg的步骤: 1. 首先,需要安装Cygwin。Cygwin是一个在Windows上运行类似于Linux的环境的工具。可以从官方网站上下载并安装。 2. 安装完Cygwin后,打开终端,输入以下命令下载x264源代码并进行编译: ``` wget http://mirror.yandex.ru/mirrors/ftp.videolan.org/x264/snapshots/last_x264.tar.bz2 bunzip2 last_x264.tar.bz2 tar -vxf last_x264.tar cd last_x264 ./configure --enable-static --enable-shared --disable-asm --disable-avs make && sudo make install ``` 3. 然后,从ffmpeg官网下载ffmpeg源代码,并进行编译。编译方法可以参考官方文档或者在终端中输入以下命令: ``` wget http://ffmpeg.org/releases/ffmpeg-[版本号].tar.gz tar -xzvf ffmpeg-[版本号].tar.gz cd ffmpeg-[版本号] ./configure --enable-shared make sudo make install ``` 其中,是你想要安装的ffmpeg的版本号。 4. 编译完成后,就可以使用ffmpeg了。可以通过在终端中输入`ffmpeg`命令来验证是否安装成功。 请注意,以上步骤仅适用于在Linux系统上安装ffmpeg。如果你是在其他操作系统上进行安装,请参考相关的文档或者教程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Windows下编译安装 FFmpeg](https://blog.csdn.net/heng615975867/article/details/119821945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值