P3113 [USACO14DEC] Marathon G
题目大意
贝茜设计了一条马拉松路线,有 \(N\) 个检查点,每个检查点有坐标。牛必须按顺序跑,但可以选择 跳过中间任意一个检查点(不能跳过起点和终点)。
两种操作:
- 查询 \(i\) 到 \(j\) 的最短时间:
- 计算从 \(i\) 跑到 \(j\) 的总距离。
- 允许跳过中间某一个点,求最短可能时间。
- 修改某个检查点的坐标:
- 更新后会影响后续查询结果。
距离计算:
- 两点的曼哈顿距离。
分析
- 首先,发现 \(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;
}
谢谢观看以及审核大大的通过!

浙公网安备 33010602011771号