4.18 省选模拟赛 消息传递 树剖 倍增 线段树维护等比数列

摘要:
完美地解释了树剖分和乘法线段树之间的联系。x是从y到根的路径上的点。很容易发现dy+ty˃=sx+dx。每次,它实际上是链上的一个查询,然后是链上一个赋值。考虑前一个树段向上跳,然后发现它不能直接从当前点跳到顶点,然后改变乘法跳。考虑到后一个赋值操作,可以发现存在一个等差序列,但不能直接赋值,因为还有一个基本值深度。然后相等序列的公差变为2。线段树+树段维护可用于修改相等序列=cc)更改;//客户˂˂t[i].ti+d[t[i].x]+2˂˂endl;}repprintf;return0;}当矿坑日志阵列按n+1排序时,不要出错。

avatar
avatar

把树剖和倍增 线段树的联系诠释的很完美。

题目意思:自行理解。

做法:设两个点x,y x能挡住y 且在k点处 那么至少的得到一个式子 tx+dx-dk<tx+dy-dk

从这个式子中可以发现 按tx+dx这个排序 前面的可以有可能挡住后面的 同时相等时题目中的要求小的编号优先。

我们考虑一个点挡住当前的这个点的去路 设sx表示x这个点当前不能通过的时间 那么当 dy-dx+ty>=sx时可以通过反之不行。且x时y到根的路径上的点。

将等式变形 容易发现 dy+ty>=sx+dx.

每次其实就是链上查询一点 然后链上赋值操作。

考虑前者 树剖向上跳 然后发现当前到top点之间不能直接跳之后换倍增跳。(树剖与倍增的一个小trick。

考虑后者 赋值操作可以发现时一个等差数列 但是还不能直接赋值 因为还有基础数值深度。

此时 赋值的时候 可以发现可以直接赋上深度就可以解决这个问题了。那么等差数列的公差就就变成了2.

线段树+树剖维护等差数列的修改即可。

真的巧妙。

const int MAXN=200010;
int n,Q,len,rt,cnt;
int f[MAXN][20],Log[MAXN],son[MAXN],id[MAXN],sz[MAXN],top[MAXN];
int lin[MAXN],ver[MAXN],nex[MAXN],pos[MAXN],d[MAXN],ans[MAXN];
struct wy{int x,ti,id;}t[MAXN];
struct jl{int l,r,sum,tag,d;}s[MAXN<<2];
inline int cmp(wy a,wy b){return a.ti+d[a.x]==b.ti+d[b.x]?a.x<b.x:a.ti+d[a.x]<b.ti+d[b.x];}
inline void add(int x,int y)
{
	ver[++len]=y;
	nex[len]=lin[x];
	lin[x]=len;
}
inline void dfs(int x,int fa)
{
	sz[x]=1;f[x][0]=fa;
	d[x]=d[fa]+1;
	rep(1,Log[d[x]],i)f[x][i]=f[f[x][i-1]][i-1];
	go(x)
	{
		dfs(tn,x);
		sz[x]+=sz[tn];
		if(sz[tn]>sz[son[x]]||!son[x])son[x]=tn;
	}
}
inline void dp(int x,int fa)
{
	id[x]=++cnt;pos[cnt]=x;top[x]=fa;
	if(!son[x])return;
	dp(son[x],fa);
	go(x)if(tn!=son[x])dp(tn,tn);
}
inline void pushup(int p){sum(p)=max(sum(zz),sum(yy));}
inline void build(int p,int l,int r)
{
	l(p)=l;r(p)=r;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(zz,l,mid);
	build(yy,mid+1,r);
}
inline void push(int p,int x,int w)
{
	d(p)=w;tag(p)=x;
	sum(p)=x+(r(p)-l(p))*w;
}
inline void pushdown(int p)
{
	int mid=(l(p)+r(p))>>1;
	push(zz,tag(p),d(p));
	push(yy,tag(p)+(mid-l(p)+1)*d(p),d(p));
	d(p)=tag(p)=0;
}
inline void change(int p,int l,int r,int x,int w)
{
	if(l==l(p)&&r==r(p)){push(p,x,w);return;}
	int mid=(l(p)+r(p))>>1;
	if(tag(p)||d(p))pushdown(p);
	if(r<=mid)change(zz,l,r,x,w);
	else 
	{
		if(l>mid)change(yy,l,r,x,w);
		else change(zz,l,mid,x,w),change(yy,mid+1,r,x+w*(mid-l+1),w);
	}
	pushup(p);
}
inline int ask(int p,int l,int r)
{
	if(l<=l(p)&&r>=r(p))return sum(p);
	int mid=(l(p)+r(p))>>1,cnt=0;
	if(d(p)||tag(p))pushdown(p);
	if(l<=mid)cnt=max(cnt,ask(zz,l,r));
	if(r>mid)cnt=max(cnt,ask(yy,l,r));
	return cnt;
}
int main()
{
	freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	get(n);get(Q);
	rep(1,n,i)add(read(),i),Log[(i+1)]=Log[(i+1)>>1]+1;
	dfs(0,0);dp(0,0);
	build(1,1,cnt);change(1,1,1,INF,0);
	rep(1,Q,i){int get(x);t[i]=(wy){x,read(),i};}
	sort(t+1,t+1+Q,cmp);
	rep(1,Q,i)
	{
		int x=t[i].x;
		while(ask(1,id[top[x]],id[x])<=t[i].ti+d[t[i].x])x=f[top[x]][0];
		fep(Log[d[x]],0,j)
		{
			if(d[f[x][j]]<d[top[x]])continue;
			if(ask(1,id[f[x][j]],id[x])<=t[i].ti+d[t[i].x])x=f[x][j];
		}
		int cc;if(ask(1,id[x],id[x])<=t[i].ti+d[t[i].x])cc=f[x][0];else cc=x;
		ans[t[i].id]=(d[t[i].x]-d[cc])*2+t[i].ti;
		x=t[i].x;
		//cout<<cc<<endl;
		while(top[cc]!=top[x])
		{
			change(1,id[top[x]],id[x],t[i].ti+d[t[i].x]-d[cc]+d[top[x]]-d[cc]+d[top[x]],2);
			//cout<<t[i].ti+d[t[i].x]-d[cc]+d[top[x]]-d[cc]+d[top[x]]<<endl;
			x=f[top[x]][0];
		}
		if(x!=cc)change(1,id[cc]+1,id[x],t[i].ti+d[t[i].x]+2,2);
		//cout<<t[i].ti+d[t[i].x]+2<<endl;
	}
	rep(1,Q,i)printf("%d ",ans[i]);
	return 0;
}

坑点 Log数组要到n+1 排序的时候别打错。

免责声明:文章转载自《4.18 省选模拟赛 消息传递 树剖 倍增 线段树维护等比数列》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle 异常处理关于安装ROS的资料备份下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

adb(16)-查看实时资源占用情况top

  命令: adb shell top 输出示例: User 0%, System 6%, IOW 0%, IRQ 0% User 3 + Nice 0 + Sys 21 + Idle 280 + IOW 0 + IRQ 0 + SIRQ 3 = 307 PID PR CPU% S #THR VSS RSS PCY UID...

3个解析url的php函数

通过url进行传值,是php中一个传值的重要手段。所以我们要经常对url里面所带的参数进行解析,如果我们知道了url传递参数名称,例如 /index.php?name=tank&sex=1#top 我们就可以通过$_GET['name'],$_GET['sex']来获得传的数据。但是如果我们不知道这些变量名又怎么办呢?这也是写这篇博文的目的,因为自...

html实现弹框,并伴随遮罩层,且弹框居中

本文介绍的内容主要实现的功能有,出现弹框,并且伴随遮罩层,且弹框一直居中。 html和js代码: <div id="hidebg"></div> <div onClick="hidebox();"> <div> <p class="box-head"...

TOP 子句用于规定要返回的记录的数目。

TOP 子句用于规定要返回的记录的数目。 1、SQL server的语法: SELECT TOP number|percent column_name(s) FROM table_name; 例子:从表persons中选取前2行的数据; SELECT TOP 2 * FROM persons; 从表persons中去前50%的 数据: SELECT TOP...

线段树_模版

线段树 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。 区间修改与求和 给出数的个数n以及操作数q:对于q:...

Atlantis(POJ1151+线段树+扫描线)

题目链接:http://poj.org/problem?id=1151 题目: 题意:求所有矩形的面积,重合部分只算一次。 思路:扫描线入门题,推荐几篇学扫描线的博客: 1.http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html 2.https://blog.csdn.ne...