bzoj 3825: [Usaco2014 Dec]Marathon

来源:互联网 发布:js语言精粹笔记 编辑:程序博客网 时间:2024/06/05 08:23
查询的答案就是完整走过所有点的距离-少走一个点可以减少的距离的最大值。
所以线段树维护区间和,还有如果不走每个点,可以少走多少路
然后答案就是sum[l+1,r]-max[l+1,r-1]
没写%lld wa了一发
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
#define ll long long
#define inf 1e9
#define eps 1e-10
#define md
#define N 100010
using namespace std;
struct Tr { ll a,b;} tr[4*N];
ll len[N],near[N],X[N],Y[N];
char st[5];
ll Abs(ll x) { return x<0?-x:x;}
ll get_dis(int i,int j) { return Abs(X[i]-X[j])+Abs(Y[i]-Y[j]);}
void build(int i,int l,int r)
{
if (l==r) { tr[i].a=len[l]; tr[i].b=near[l]; return;}
int mid=(l+r)>>1;
build(i<<1,l,mid); build(i<<1|1,mid+1,r);
tr[i].a=tr[i<<1].a+tr[i<<1|1].a;
tr[i].b=max(tr[i<<1].b,tr[i<<1|1].b);
}
ll qsum(int i,int l,int r,int ql,int qr)
{
if (ql<=l&&r<=qr) return tr[i].a;
int mid=(l+r)>>1;
if (qr<=mid) return qsum(i<<1,l,mid,ql,qr);
if (mid+1<=ql) return qsum(i<<1|1,mid+1,r,ql,qr);
return qsum(i<<1,l,mid,ql,qr)+qsum(i<<1|1,mid+1,r,ql,qr);
}
ll qmax(int i,int l,int r,int ql,int qr)
{
if (ql<=l&&r<=qr) return tr[i].b;
int mid=(l+r)>>1;
if (qr<=mid) return qmax(i<<1,l,mid,ql,qr);
if (mid+1<=ql) return qmax(i<<1|1,mid+1,r,ql,qr);
return max(qmax(i<<1,l,mid,ql,qr),qmax(i<<1|1,mid+1,r,ql,qr));
}
void modify(int i,int l,int r,int x)
{
if (l==r) { tr[i].a=len[l]; tr[i].b=near[l]; return;}
int mid=(l+r)>>1;
if (x<=mid) modify(i<<1,l,mid,x); else modify(i<<1|1,mid+1,r,x);
tr[i].a=tr[i<<1].a+tr[i<<1|1].a;
tr[i].b=max(tr[i<<1].b,tr[i<<1|1].b);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%lld%lld",&X[i],&Y[i]);
for (int i=2;i<=n;i++) len[i]=get_dis(i-1,i);
for (int i=2;i<n;i++) near[i]=len[i]+len[i+1]-get_dis(i-1,i+1);
build(1,1,n);
while (m--)
{
scanf("%s",st);
if (st[0]=='Q')
{
int l,r;
scanf("%d%d",&l,&r);
if (l==r) printf("0\n");
else
{
ll sum=qsum(1,1,n,l+1,r);
if (l<r-1) sum-=qmax(1,1,n,l+1,r-1);
printf("%lld\n",sum);
}
}
else
{
int i;
scanf("%d",&i); scanf("%lld%lld",&X[i],&Y[i]);
len[i]=get_dis(i-1,i); len[i+1]=get_dis(i,i+1);
if (i>1) near[i-1]=len[i-1]+len[i]-get_dis(i-2,i);
near[i]=len[i]+len[i+1]-get_dis(i-1,i+1);
near[i+1]=len[i+1]+len[i+2]-get_dis(i,i+2);
if (i) modify(1,1,n,i-1);
modify(1,1,n,i);
if (i<n) modify(1,1,n,i+1);
}
}
return 0;
}

0 0
原创粉丝点击