首页 > 其他分享 >P9447 [ICPC2021 WF] Spider Walk 题解

P9447 [ICPC2021 WF] Spider Walk 题解

时间:2023-11-27 19:13:53浏览次数:39  
标签:WF ICPC2021 return tagr int 题解 void tagl inline

更好的阅读体验

很有意思的一道题。

设 \(f_i\) 表示第 \(i\) 根线的答案,首先有一个关键结论:任意两根相邻的线答案只差一定小于 \(1\)。原因显然,可以在无限远的地方加一根线来构造。该结论可以扩展一下,对于距离为 \(d\) 的两根线,答案之差不会超过 \(d\)。

考虑进行倒着加线,考虑加了一根线会有什么影响:首先会把这两根线的答案交换,然后用上面的结论去更新答案。

对于交换的两根线,交换了之后不一定是最优解,可能可以用其他线的答案更新,这个东西似乎不太好高效维护。

但是事实上,只用左右相邻的两根线来更新代价就是对的。如果存在使用距离它大于等于 \(2\) 的线来更新它的答案比和它相邻的线优秀,假设用来更新的线在此线的右边,则一定有:

\[f_x+x-i>f_{i+1}+1 \]

移一下项,

\[f_{i+1}-f_x>x-(i+1) \]

与结论相悖,所以原命题正确。接下来考虑用这两根线去更新其他线的答案。发现操作本质是对 \(i\in [l,r]\) 的 \(i\) 执行 \(f_i=\min(f_i,k+i)\)(或者 \(i\) 的符号相反),可以直接 segment beats 线段树维护。用 \(tagl,tagr\) 分别表示左边和右边取 \(\min\) 的最小值,下传标记的细节见代码。

	int n,m,s;
	namespace Segment
	{
		struct{int l,r,tagl,tagr;}t[800010];
		inline void downl(int p,int tagl){t[p].tagl=min(t[p].tagl,tagl);}
		inline void downr(int p,int tagr){t[p].tagr=min(t[p].tagr,tagr);}
		inline void spread(int p)
		{
			downl(p*2,t[p].tagl),downl(p*2+1,t[p].tagl+t[p*2+1].l-t[p*2].l);
			downr(p*2+1,t[p].tagr),downr(p*2,t[p].tagr+t[p*2+1].r-t[p*2].r);
			t[p].tagl=t[p].tagr=INF;
		}
		void build(int p,int l,int r)
		{
			t[p].l=l,t[p].r=r,t[p].tagl=t[p].tagr=INF;
			if(l==r)return;
			int mid=l+((r-l)>>1);
			build(p*2,l,mid),build(p*2+1,mid+1,r);
		}
		int ask(int p,int x)
		{
			if(t[p].l==t[p].r)return min(t[p].tagl,t[p].tagr);
			return spread(p),x<=t[p*2].r?ask(p*2,x):ask(p*2+1,x);
		}
		void modifys(int p,int x,int y)
		{
			if(t[p].l==t[p].r)return t[p].tagl=t[p].tagr=y,void();
			spread(p);
			if(x<=t[p*2].r)modifys(p*2,x,y);else modifys(p*2+1,x,y);
		}
		void modifyl(int p,int x,int y)
		{
			if(x<=t[p].l)return downl(p,y+t[p].l-x);
			spread(p),modifyl(p*2+1,x,y);
			if(x<=t[p*2].r)modifyl(p*2,x,y);
		}
		void modifyr(int p,int x,int y)
		{
			if(x>=t[p].r)return downr(p,y+x-t[p].r);
			spread(p),modifyr(p*2,x,y);
			if(x>t[p*2].r)modifyr(p*2+1,x,y);
		}
		inline void change(int x,int y){modifyl(1,x,y),modifyr(1,x,y),modifyl(1,1,n-x+1+y),modifyr(1,n,x+y);}
	}
	using namespace Segment;
	pii a[500010];
	inline bool cmp(pii p1,pii p2){return p1.fi>p2.fi;}
	inline void mian()
	{
		read(n,m,s),build(1,1,n),change(s,0);
		for(int i=1;i<=m;++i)read(a[i]);
		sort(a+1,a+1+m,cmp);
		for(int i=1;i<=m;++i)
		{
			a[i].fi=a[i].se,a[i].se=a[i].fi%n+1;
			int lef=ask(1,a[i].fi),rig=ask(1,a[i].se);
			swap(lef,rig);
			modifys(1,a[i].fi,lef),modifys(1,a[i].se,rig);
			int Minl=ask(1,a[i].fi-1==0?n:a[i].fi-1);
			if(Minl+1<lef)modifys(1,a[i].fi,Minl+1);
			Minl=ask(1,a[i].se==n?1:a[i].se+1);
			if(Minl+1<rig)modifys(1,a[i].se,Minl+1);
			change(a[i].fi,lef),change(a[i].se,rig);
		}
		for(int i=1;i<=n;++i)write(ask(1,i),'\n');
	}

标签:WF,ICPC2021,return,tagr,int,题解,void,tagl,inline
From: https://www.cnblogs.com/WrongAnswer90-home/p/17860148.html

相关文章

  • CF1900 C Anji's Binary Tree 题解
    LinkCF1900CAnji'sBinaryTreeQuestion给出一个树,每个节点上有一个字母L/R/U,从\(1\)号根节点开始,L表示接下来走到左节点,R表示接下来走到右节点,U表示接下载走到父节点问,最少修改几个节点上的字母使得从根节点走到叶子节点Solution定义\(F_x\)表示从\(x\)走到叶......
  • P7626 [COCI2011-2012#1] MATRIX( 普及/提高− ) 题解
    题目传送门思路:首先思考暴力,\(O(n^4)\)的时间复杂度,不行。那么我们这里就要运用到一点前缀和的知识了。我们可以用前缀和对两条对角线进行计数。每个点有两个对角线运算。差不多是\(O(n^2)\)到\(O(n^3)\)的时间复杂度。而\(n\leq400\)稳过。Code:#include<bits/stdc......
  • 【Windows】你所不知道的UWF
    接到boss的要求,要求所有会议室电脑在零时自动重启,且重启后会自动恢复备份系统这时候我的老哥告诉我,可以用Windows自带的一个功能——UWF!WHAT?UWF?是UFO的弟弟吗?接下来,介绍我使用UWF的辛苦过程(难受加班了一个月)UWF统一写入筛选器ok我们已经明确了领导的具体需求,这时候我先在一个......
  • Snowflake Snow Snowflakes[PKUOJ 3349]
    这是一道蓝书上的哈希例题。相对简单。题面DescriptionYoumayhaveheardthatnotwosnowflakesarealike.Yourtaskistowriteaprogramtodeterminewhetherthisisreallytrue.Yourprogramwillreadinformationaboutacollectionofsnowflakes,andsear......
  • 复旦大学数学学院23级高等代数I期中考试精选大题解答
    四、求解下列线性方程组,其中$a_1,\cdots,a_n,b$为参数且$\sum\limits_{i=1}^na_i\neq0$:$$\begin{cases} (a_1+b)x_1+a_2x_2+a_3x_3+\cdots+a_nx_n=0,\\ a_1x_1+(a_2+b)x_2+a_3x_3+\cdots+a_nx_n=0,\\ a_1x_1+a_2x_2+(a_3+b)x_3+\cdots+a_nx_n=0,\\ \hfill\cdots\cdots......
  • CF1900 B Laura and Operations 题解
    LinkCF1900BLauraandOperationsQuestion给出\(1,2,3\)的个数\(a,b,c\)可以分别减少两个不同的数,增加一个与两个数都不同的数问,是否能经过一些操作使得就剩下\(1\)或\(2\)或\(3\)Solution先考虑\(1,2,3\)其实是等价的,所以我们只需要考虑把\(2,3\)全都变成......
  • CF1900 A Cover in Water 题解
    LinkCF1900ACoverinWaterQuestion给出一个\(n\)个格子,有些格子被堵塞了,有些格子是空的,我需要在进行一些操作,使得所有空的格子里面都有水操作1:给任意一个格子装上水操作2:把一格水从一个地方搬运到另外一个空的格子里如果一个空的格子的相邻的两个格子都有水,那么这......
  • Live Server插件打开浏览器时:该网页无法正常运作,127.0.0.1未发送任何数据的问题解决
    一、问题复现今天使用VsCode写HTML代码时,使用LiveServer打开预览时,发现浏览器显示“该网页无法正常运作,127.0.0.1未发送任何数据”的问题。二、解决办法1.在左侧工具栏找到扩展商店,找到LiveServer,然后点击对应的小齿轮,进入插件设置。2.选择ExtensionSettings3.进入......
  • ABC330 A-E 题解
    ABC330题解AtCoderBeginnerContest330A-CountingPasses思路:枚举一遍,当前数大于\(L\)使\(ans+1\)即可.代码:#include<iostream>#defineintlonglongusingnamespacestd; intn,l,ans;intx; signedmain(){ cin>>n>>l; for(inti=1;i&......
  • Information Graph 题解
    题目链接InformationGraph分析在线并不好做,考虑离线,先将树建出来\(2\)操作时\(x\)节点与当前根节点之间的点都会获得文件当前根节点可以用并查集维护对于查询的节点判断它是否为链上的点即可具体的,若该节点为\(rt\)子树中的点且该节点的子树包含\(x\)节点,它就......