【XSY3551】Inserting Lines(线段树)

题意:数轴上有无穷个格子,每个坐标上各有一个格子,你需要支持以下操作共 n n n 次:

  • x = k x=k x=k 这个格子前插入一个格子,并将所有 x ≥ k x\geq k xk 的格子后移一位。时间++。
  • 询问当前 x = k x=k x=k 这个格子在时刻 t i m tim tim 的坐标。

n ≤ 5 × 1 0 5 , x ≤ 1 0 9 n\leq 5\times 10^5,x\leq 10^9 n5×105,x109

推了一会好像不能用可持久化的东西维护,可能是我姿势有问题。

普通的树套树是外层平衡树维护坐标维度,内层动态开点线段树维护时间维度。修改转变为第一维区间、第二维单点,询问转变为第一维单点、第二维单点。时间复杂度 O ( n log ⁡ 2 n ) O(n\log ^2n) O(nlog2n),而且外层貌似只能用替罪羊树,因为不能转(父子关系不能变)。

介绍一个常数更小的 O ( n log ⁡ 2 n ) O(n\log ^2n) O(nlog2n) 的做法:

考虑外层用线段树维护时间维度,然后线段树上每个节点 u u u 存储一个有序数组 a u a_u au:表示 u u u 代表时间区间 [ l , r ] [l,r] [l,r] 内进行的操作一所插入的所有格子在时刻 r r r 时的坐标。

维护这个数组的目的是:假设我们知道某个格子在时刻 r r r 时的坐标 x x x,我们想将时间倒流,得到它在时刻 l l l 时的坐标 x ′ x' x(假设它那时也存在),那么我们只需要用 x x x 减去 a u a_u au 中小于等于 x x x 的数的个数即可得到 x ′ x' x,即减掉时间区间 [ l , r ] [l,r] [l,r] 内操作一的影响。

那么询问的时候假设我们已经找到了 x = k x=k x=k 这个格子是 s t st st 时刻被插入的(如果没有置为 0 0 0),假设当前时刻为 n o w now now,然后我们直接在线段树上逆序处理时间区间 [ s t , n o w ] [st,now] [st,now] 内的所有操作一的影响即可。而找到 x = k x=k x=k 这个格子是在什么时候被插入的的方法类似。询问的时间复杂度为 O ( n log ⁡ 2 n ) O(n\log ^2n) O(nlog2n)

那么我们现在考虑如何维护这个数组了。首先就是 merge 的问题,普通的做法是拿 a l c a_{lc} alc a r c a_{rc} arc 上二分找出位置。但由于现在两个数组都是有序的,所以可以直接使用双指针做到 O ( ∣ a l c ∣ + ∣ a r c ∣ ) O(|a_{lc}|+|a_{rc}|) O(alc+arc)

显然我们直接每次修改都从叶子往上 merge 的时间复杂度是有问题的。但有一个神奇的技巧:每次我们在时刻 k k k 修改某个叶子时,我们只更新那些 r = k r=k r=k 的区间。原因很简单:首先 r < k r<k r<k 的区间我们不会影响到,其次对于那些 r > k r>k r>k 的区间,在下一次操作一之前的询问我们都不会问到它,所以这些区间是暂时不需要更新的。换言之,只有当本区间内的所有操作都发生之后,我们才更新这个区间。这样能保证每个区间只被更新一次,修改的总时间复杂度也就是 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的了。

本题是放到二维的情况,不过也是类似的。

代码如下:

#include<bits/stdc++.h>

#define N 100010

using namespace std;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int Q;

struct Solve
{
	int n,opt[N];
	vector<int>nx[N<<2];
	void up(int k)
	{
		assert(nx[k].empty());
		int lc=k<<1,rc=k<<1|1,tmp=0;
		for(int i=0;i<(int)nx[rc].size();i++)
		{
			while(tmp<(int)nx[lc].size()&&nx[lc][tmp]<=nx[rc][i]-1-i)
				nx[k].push_back(nx[lc][tmp]+i),tmp++;
			nx[k].push_back(nx[rc][i]);
		}
		while(tmp<(int)nx[lc].size())
			nx[k].push_back(nx[lc][tmp]+(int)nx[rc].size()),tmp++;
	}
	void update(int k,int l,int r,int x)
	{
		if(l==r)
		{
			nx[k].push_back(x);
			return;
		}
		int mid=(l+r)>>1;
		if(n<=mid) update(k<<1,l,mid,x);
		else update(k<<1|1,mid+1,r,x);
		if(r==n) up(k);
	}
	void update(int tim,int x)
	{
		opt[++n]=tim;
		update(1,1,Q,x);
	}
	int rollback(int k,int x)
	{
		int tmp=lower_bound(nx[k].begin(),nx[k].end(),x)-nx[k].begin();
		assert(tmp==(int)nx[k].size()||x!=nx[k][tmp]);
		return x-tmp;
	}
	int qtim(int k,int l,int r,int &x)
	{
		if(r<=n)
		{
			int tmp=lower_bound(nx[k].begin(),nx[k].end(),x)-nx[k].begin();
			if(tmp==(int)nx[k].size()||x!=nx[k][tmp])
			{
				x-=tmp;
				return 0;
			}
		}
		if(l==r) return l;
		int mid=(l+r)>>1;
		if(n>mid)
		{
			int tmp=qtim(k<<1|1,mid+1,r,x);
			if(tmp) return tmp;
		}
		return qtim(k<<1,l,mid,x);
	}
	int qtim(int x)
	{
		if(!n) return 0;
		return opt[qtim(1,1,Q,x)];
	}
	void query(int k,int l,int r,int st,int &x)
	{
		if(st<=l&&r<=n)
		{
			x=rollback(k,x);
			return;
		}
		int mid=(l+r)>>1;
		if(n>mid) query(k<<1|1,mid+1,r,st,x);
		if(st<=mid) query(k<<1,l,mid,st,x);
	}
	void query(int tim,int &x)
	{
		int st=upper_bound(opt+1,opt+n+1,tim)-opt;
		if(st<=n) query(1,1,Q,st,x);
	}
}tx,ty;

void query(int &x,int &y)
{
	int xtim=tx.qtim(x),ytim=ty.qtim(y);
	if(!xtim&&!ytim)
	{
		tx.query(0,x),ty.query(0,y);
		return;
	}
	if(xtim>ytim)
	{
		x=xtim;
		ty.query(xtim,y);
	}
	else
	{
		y=ytim;
		tx.query(ytim,x);
	}
}

int main()
{
	Q=read();
	int lx=0,ly=0;
	for(int tim=1;tim<=Q;tim++)
	{
		int opt=read();
		if(opt==1) ty.update(tim,read()+lx+ly);
		if(opt==2) tx.update(tim,read()+lx+ly);
		if(opt==3)
		{
			int x=read()+lx+ly,y=read()+lx-ly;
			query(x,y);
			printf("%d %d\n",lx=x,ly=y);
		}
	}
	return 0;
}
根据提供的引用内容,你遇到的问题是在发送HTTP POST请求时收到了403 Forbidden的错误。这个错误通常表示你没有权限访问所请求的资源。 要解决这个问题,你可以采取以下步骤: 1. 首先,确保你的请求URL正确,并且你有权限访问该URL。你可以尝试在浏览器中直接访问该URL,看看是否能够成功访问。 2. 如果你确定URL是正确的,并且你有权限访问,那么可能是你的请求中缺少了必要的身份验证信息。你可以检查你的请求头中是否包含了正确的身份验证信息,比如Token或用户名密码。 3. 另外,你还可以检查服务器端的配置,确保你的请求被正确地处理和授权。你可以查看服务器的日志,以了解更多关于403错误的详细信息。 综上所述,当你收到403 Forbidden错误时,你应该首先检查URL和权限,然后确保请求中包含了正确的身份验证信息。如果问题仍然存在,你可以进一步检查服务器端的配置和日志,以找出问题的根本原因。 #### 引用[.reference_title] - *1* [kubeadm init报错10248...(The HTTP call equal to ‘curl -sSL http://localhost:10248/healthz‘ failed)](https://blog.youkuaiyun.com/weixin_45969972/article/details/123529966)[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^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [c/c++使用libcurl库做http客户端及封装(HTTP_GET和HTTP_POST)](https://blog.youkuaiyun.com/xsy29000/article/details/103181267)[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^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值