首页 > 其他分享 >CF1924B Space Harbour

CF1924B Space Harbour

时间:2024-01-31 20:35:49浏览次数:20  
标签:CF1924B val Space int ll tr Harbour now dis

思路

可以观察到一件事情:在两个港口之间的船他们对应的价值都是一样的,都为左边港口的权值。因此对于这段区间的价值和就可以写成 \(val \times \sum dis\) 的形式,\(\sum dis\) 便为这些船到右边港口的距离和。那么我们就可以按照港口把序列分成很多个区间来考虑。

港口用一个 set 维护,这样能很方便的插入以及找前驱后继。每次插入一个新港口时,设它左边第一个港口在 \(l\),右边第一个在 \(r\),他自己在 \(now\)。\(now\) 就把 \(l,r\) 分成了两个新的区间,我们就需要进行区间修改,不难想到用线段树维护,维护的值就是一段区间的 \(val,\sum dis\) 以及整个区间的答案。对于 \((now,r]\) 这个区间,他们的 \(\sum dis\) 没有改变,只是 \(val\) 变成了新输入的 \(v\),用懒标记区间赋值 \(val\) 即可。对于 \([l,now)\) 改变的就是 \(\sum dis\),但是因为有一个 \(\sum\),不能区间推平了,必须换个角度思考。把 \(\sum dis\) 拆成每个点单独的 \(dis\),一开始是每个点到 \(r\) 的距离,现在变成了每个点到 \(now\) 的距离,减少的就是 \(r-now\)!于是把区间中的所有点都减去一个 \(r-now\),相当于 \(\sum dis\) 减去了 \(len \times (r-now)\),把 \(r-now\) 用懒标记记录下来,这是可以下传的,就维护好了。至于 \([now,now]\) 这个点,全部变成 \(0\) 即可。

pushup 把左右儿子的 \(dis\) 都加起来,\(val\) 赋为左儿子的 \(val\),区间答案直接 \(\sum dis \times val\)(我们只考虑每两个港口间的区间,不考虑跨区间的东西,因此可以直接用这个式子算答案)。

code

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define ls p<<1
#define rs p<<1|1
using namespace std;
int t;
const int N=3e5+5;
int n,m,q;
ll val[N],x[N];
set<ll>s;//维护港口
struct Tree{
	int l,r;
	ll sum;
	ll dis,val;
	ll ad,vl; //ad dis的懒标记,vl val的懒标记
}tr[N<<4];
inline void pushup(int p){
	tr[p].dis=tr[ls].dis+tr[rs].dis;
	tr[p].val=tr[ls].val;
	tr[p].sum=tr[ls].sum+tr[rs].sum;
}
inline void pushdown(int p){
	if(!tr[p].ad && !tr[p].vl)return;
	ll ds=tr[p].ad,vl=tr[p].vl;
	if(vl)tr[ls].val=vl,tr[rs].val=vl;
	tr[ls].dis-=(tr[ls].r-tr[ls].l+1)*ds;
	tr[rs].dis-=(tr[rs].r-tr[rs].l+1)*ds;
	tr[ls].sum=tr[ls].val*tr[ls].dis;
	tr[rs].sum=tr[rs].val*tr[rs].dis;
	tr[ls].ad+=ds;tr[rs].ad+=ds;
	if(vl)tr[ls].vl=vl,tr[rs].vl=vl;
	tr[p].ad=0;tr[p].vl=0;
	
}
void build(int p,int l,int r){
	tr[p].l=l;tr[p].r=r;
	if(l==r){
		auto nxt=s.lower_bound(l);//后继
		if((*nxt)==l)return;
		auto now=nxt;
		now--;
		tr[p].val=val[*now];
		tr[p].dis=(*nxt)-l;
		tr[p].sum=tr[p].val*tr[p].dis;
		return;
	}
	int mid=l+r>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(p);
}
void updatedis(int p,int l,int r,ll d){
	if(tr[p].l>=l&&tr[p].r<=r){
		tr[p].dis-=(tr[p].r-tr[p].l+1)*d;
		tr[p].sum=tr[p].dis*tr[p].val;
		tr[p].ad+=d;
		return;
	}
	pushdown(p);
	int mid=tr[p].l+tr[p].r>>1;
	if(l<=mid)updatedis(ls,l,r,d);
	if(r>mid)updatedis(rs,l,r,d);
	pushup(p);
}
void updateval(int p,int l,int r,ll d){
	if(tr[p].l>=l&&tr[p].r<=r){
		tr[p].val=d;
		tr[p].vl=d;
		tr[p].sum=tr[p].dis*tr[p].val;
		return;
	}
	pushdown(p);
	int mid=tr[p].l+tr[p].r>>1;
	if(l<=mid)updateval(ls,l,r,d);
	if(r>mid)updateval(rs,l,r,d);
	pushup(p);
}
ll query(int p,int l,int r){
	if(tr[p].l>=l&&tr[p].r<=r)return tr[p].sum;
	pushdown(p);
	int mid=tr[p].l+tr[p].r>>1;
	ll res=0;
	if(l<=mid)res+=query(ls,l,r);
	if(r>mid)res+=query(rs,l,r);
	return res;
}
void modify(int p,int x){
	if(tr[p].l==tr[p].r){
		tr[p].dis=tr[p].val=tr[p].ad=tr[p].vl=tr[p].sum=tr[p].val=0;
		return;
	}
	int mid=tr[p].l+tr[p].r>>1;
	if(x<=mid)modify(ls,x);
	else modify(rs,x);
	pushup(p);
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n>>m>>q;
	for(int i=1;i<=m;++i)cin>>x[i],s.insert(x[i]);
	for(int i=1;i<=m;++i)cin>>val[x[i]];
	build(1,1,n);
	while(q--){
		int op;
		ll l,r;
		cin>>op>>l>>r;
		if(op==1){
			s.insert(l);val[l]=r;
			auto pos=s.find(l);
			auto pre=pos,nxt=pos;
			pre--;nxt++; 
			ll prex=*pre;
			ll nxtx=*nxt;
			if(prex+1<l)updatedis(1,prex+1,l-1,(nxtx-l)); //更新左区间的dis
			if(l+1<nxtx)updateval(1,l+1,nxtx-1,r);//右区间的val
			modify(1,l);
		}
		else cout<<query(1,l,r)<<endl;
	}
	return 0;
}

标签:CF1924B,val,Space,int,ll,tr,Harbour,now,dis
From: https://www.cnblogs.com/sunsetlake/p/18000039

相关文章

  • Powershell 并发任务 | Runspace 线程 | 结果获取
    介绍在PowerShell中进行多任务处理(Multithreading或ParallelProcessing)主要目的是提高脚本的执行效率和性能。对于需要处理大量数据或执行多个独立任务的脚本来说尤其有用。提高性能:多任务处理允许脚本同时执行多个任务,从而加快整体执行速度。对于需要处理大型数据集或执......
  • CF1924B
    Solution考虑维护任意两个相邻码头之间的费用总和,设\(val_i\)表示第\(i\)个码头与第\(i+1\)个码头之间所有船到达下一个码头的费用之和。此时计算\(val\)数组在初始时,与修改时都能够做到\(O(1)\)。用set来维护码头的位置,方便在新建码头时快速找到前驱和后继的位置......
  • CodeForces 1924B Space Harbour
    洛谷传送门CF传送门不知道为什么好像大家在这题上花了挺久的。发现对于一对相邻的港口\((x_i,x_{i+1})\),\(x\in(x_i,x_{i+1})\)的花费是\(y_i(x_{i+1}-x)\)。拆开得\(y_ix_{i+1}-y_ix\)。考虑用set维护所有港口,这样可以知道一个港口左边和右边的港......
  • VBA001 String、Space関数
    VBAで全角スペースを指定数追加する(String)VBAで半角スペースを指定数追加する(Space)1,String関数の使用方法構文String(Number,Character)説明Number:文字をいくつ並べるのかを整数値で指定します。Character:文字の文字コード、または文字列を指定します。この文字が引数Nu......
  • SciTech-Math-AdvancedAlgebra-Linear Spaces(Vector Spaces) and Subspace: The Colu
    https://math.mit.edu/~gs/dela/dela_5-1.pdfhttps://people.math.harvard.edu/~knill/teaching/math22b2019/handouts/lecture01.pdfhttps://web.stanford.edu/group/dabmgroup/cgi-bin/dabm/wp-content/uploads/2021/12/Lecture_14.pdfN-elementorderedNumberSequence......
  • k8s 核心概念 namespace、pod、deployment、service
    1、NamespaceNamespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。k8s在集群启动之后,会默认创建几个namespace。[root@master~]#kubectlgetnamespaceNAMESTATUSAGEdefaultActive......
  • openEuler欧拉安装Jenkins并修改构建workspace路径
    一、系统优化关闭防火墙systemctlstopfirewalldsystemctldisablefirewalld关闭selinuxsed-ri's/SELINUX=enforcing/SELINUX=disabled/'/etc/selinux/configsetenforce0二、安装Jenkinssudowget-O/etc/yum.repos.d/jenkins.repohttps://pkg.jenkins.io/redhat-stable/je......
  • openGauss学习笔记-191 openGauss 数据库运维-常见故障定位案例-出现Error:No space l
    openGauss学习笔记-191openGauss数据库运维-常见故障定位案例-出现Error:Nospaceleftondevice提示191.1出现“Error:Nospaceleftondevice”提示191.1.1问题现象在数据库使用过程中,出现如下错误提示。Error:Nospaceleftondevice191.1.2原因分析磁盘空间不足......
  • 欧拉openEuler安装Jenkins并修改构建workspace路径
    ​一、系统优化关闭防火墙systemctlstopfirewalldsystemctldisablefirewalld关闭selinuxsed-ri's/SELINUX=enforcing/SELINUX=disabled/'/etc/selinux/configsetenforce0二、安装Jenkinssudowget-O/etc/yum.repos.d/jenkins.repohttps://pkg.jenkins.io......
  • SpaceDesk如何连接平板/PC(生产力副屏)
    1、下载安装分为安卓端和PC端,两个设备都需要安装对应的软件。SpaceDesk官网https://link.zhihu.com/?target=http%3A//spacedesk.net/需要魔法上网。安装过程比较简单,无脑下一步即可。我已经把安装包准备好了,如果不想自己找,可以去我的微信订阅号:靠谱杨阅读人生,回复【PC】获取安卓......