P3113 [USACO14DEC] Marathon G

题目大意

贝茜设计了一条马拉松路线,有 \(N\) 个检查点,每个检查点有坐标。牛必须按顺序跑,但可以选择 跳过中间任意一个检查点(不能跳过起点和终点)。

两种操作:

  1. 查询 \(i\)\(j\) 的最短时间
    • 计算从 \(i\) 跑到 \(j\) 的总距离。
    • 允许跳过中间某一个点,求最短可能时间。
  2. 修改某个检查点的坐标
    • 更新后会影响后续查询结果。

距离计算:

  • 两点的曼哈顿距离。

分析

  • 首先,发现 \(N,Q \leq 100000\),猜想时间复杂度 \(O(n \log n)\)
  • 看到修改与查询,可以想到是数据结构题。
  • 最后很简单可以想到删去一个点,相当于前后两个点直接走,那么就很明显可以维护删点后可以优化的最大值,此处有线段树,区间求和,我们就可以用树状数组简单维护(注意:修改一个点还会影响前后的点)。

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN=1e5+7;
int n,Q,ans,d[MAXN];

struct node {
	int x,y;
} a[MAXN];

int dis(int x)
{
	if(!x)
		return 0;
	return abs(a[x].x-a[x+1].x)+abs(a[x].y-a[x+1].y);
}

int Dis(int x)
{
	if(!x)
		return 0;
	return abs(a[x-1].x-a[x+1].x)+abs(a[x-1].y-a[x+1].y);
}

struct Tree {
	int val,id;
};

struct Bit {
	int tr[MAXN];
	
	int lowbit(int x)
	{
		return x&-x;
	}
	
	void add(int x,int val)
	{
		while(x<=n)
		{
			tr[x]+=val;
			x+=lowbit(x);
		}
		return ;
	}
	
	int query(int x)
	{
		int res=0;
		while(x)
		{
			res+=tr[x];
			x-=lowbit(x);
		}
		return res;
	}
} B;

#define lson (p<<1)
#define rson (p<<1|1)

struct Segmentree {
	Tree tr[MAXN<<2];
	
	void build(int l,int r,int p)
	{
		if(l==r)
		{
			tr[p]={abs(dis(l)+dis(l-1)-Dis(l)),l};
			return ;
		}
		int mid=(l+r)>>1;
		build(l,mid,lson);
		build(mid+1,r,rson);
		if(tr[lson].val>tr[rson].val)
			tr[p]=tr[lson];
		else
			tr[p]=tr[rson];
		return ;
	}
	
	void update(int s,int t,int p,int x,int val)
	{
		if(s>x or t<x)
			return ;
		if(s==t)
		{
			tr[p].val=val;
			return ;
		}
		int mid=(s+t)>>1;
		update(s,mid,lson,x,val);
		update(mid+1,t,rson,x,val);
		if(tr[lson].val>tr[rson].val)
			tr[p]=tr[lson];
		else
			tr[p]=tr[rson];
		return ;
	}
	
	Tree query(int s,int t,int p,int l,int r)
	{
		if(s>r or t<l)
			return (Tree){-1,-1};
		if(s>=l and t<=r)
			return tr[p];
		int mid=(s+t)>>1;
		Tree resl=query(s,mid,lson,l,r);
		Tree resr=query(mid+1,t,rson,l,r);
		if(resl.val>resr.val)
			return resl;
		return resr;
	}
} T;

signed main()
{
	scanf("%d %d",&n,&Q);
	for(int i=1;i<=n;i++)
		scanf("%d %d",&a[i].x,&a[i].y);
	for(int i=2;i<=n;i++)
		B.add(i,dis(i-1));
	T.build(2,n-1,1);
	while(Q--)
	{
		char ch=getchar();
		while(ch!='U' and ch!='Q')
			ch=getchar();
		if(ch=='U')
		{
			int id,x,y;
			scanf("%d %d %d",&id,&x,&y);
			B.add(id,-dis(id-1));
			B.add(id+1,-dis(id));
			a[id]={x,y};
			B.add(id,dis(id-1));
			B.add(id+1,dis(id));
			if(id>=2 and id<=n-1)
			{
				T.update(2,n-1,1,id,dis(id-1)+dis(id)-Dis(id));
				if(id-1>=2)
					T.update(2,n-1,1,id-1,dis(id-2)+dis(id-1)-Dis(id-1));
				if(id+1<=n-1)
					T.update(2,n-1,1,id+1,dis(id+1)+dis(id)-Dis(id+1));
			}
		}
		else
		{
			int l,r;
			scanf("%d %d",&l,&r);
			ans=B.query(r)-B.query(l);
			if(r-l+1>2)
			{
				Tree res=T.query(2,n-1,1,l+1,r-1);
				ans=ans-(dis(res.id)+dis(res.id-1))+Dis(res.id);
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}

谢谢观看以及审核大大的通过!

posted @ 2026-01-04 11:31  HHMing  阅读(2)  评论(0)    收藏  举报