51nod 1593 公园晨跑
来源:互联网 发布:废铁战士淘宝可靠吗 编辑:程序博客网 时间:2024/04/30 16:00
51nod 1593 公园晨跑
原题链接
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1593
题目中,猴子消耗的能量等于:
两个点的距离加上两个点上 树的高度的2倍
我们可以把环撕开,变为链,因为路径是环上连续的一段。
任何一段都可以映射到序列:
1,2,3,4,...n,1,2,3,4,...n
把询问环,变为某一个区间
令 ,第i棵树的高度为
hi
令,第1个点在0位置,第i个点相对于第1个点的位置为:
di
如果,选定 x,y作为猴子选择的两个棵树的编号,那么它消耗的能量为:
∣∣dx−dy∣∣+2hx+2hy
令 x<y
∣∣dx−dy∣∣+2hx+2hy=dy−dx+2hx+2hy=(dy+2hy)−(dx−2hx)
令 :
A[x]=dx+2hxB[x]=dx−2hx
原问题等价于计算,指定区间[L,R] 内:
maxx,y∈[L,R] , x≠y(A[x]−B[y])
假设 x=X,y=Y 时 有:
maxx∈[L,R]A[x]=A[X]miny∈[L,R]B[y]=B[Y]
当 X≠Y 时:
maxx,y∈[L,R] , x≠y(A[x]−B[y])=A[X]−B[Y]
当X=Y 时:
假设有 满足下面等式的a,b
maxx,y∈[L,R] , x≠y(A[x]−B[y])=A[a]−B[b]
如果 a≠X 且b≠Y ,又因为 ,A[X]>A[a] ,B[Y]<B[b]
所以:
A[X]−B[b]>A[a]−B[b]A[a]−B[Y]>A[a]−B[b]
与上文矛盾。
所以有:a=X 或者 b=Y ,且二者不同时成立
所以,利用线段树求出区间最大值(A中)与最小值(B中)的下标,
如果两个最值在同一个位置,即X=Y 则枚举:
a=X 时的答案,有:
B[b]=miny∈[L,R],y≠YB[y]
b=Y 时的答案,有:
A[a]=maxx∈[L,R],x≠XB[x]
#include <stdio.h>#include <algorithm>#include <string.h>#define MAXN 300005using namespace std;typedef long long LL;typedef pair<LL,LL>P;struct point{ int c[2]; LL ma; int x; point() { c[0]=c[1]=0; ma=-0x3f3f3f3f3f3f3f3f; }};struct Bt{ point A[MAXN*8]; int deep; int root; LL ma; LL key; int xx; int n; Bt() { root=1; deep=2; } void update(point &a) { if(A[a.c[0]].ma>A[a.c[1]].ma) { a.ma=A[a.c[0]].ma; a.x=A[a.c[0]].x; } else { a.ma=A[a.c[1]].ma; a.x=A[a.c[1]].x; } } void _insert(int x,int L,int R,int &k) { if(x>R||x<L)return ; if(!k)k=deep++; if(L==R) { A[k].ma=key; A[k].x=x; return ; } int mid=(L+R)>>1; _insert(x,L,mid,A[k].c[0]); _insert(x,mid+1,R,A[k].c[1]); update(A[k]); } void insert(int x,LL ke) { key=ke; _insert(x,0,n,root); } void _query(int l,int r,int L,int R,int k) { if(R<l||L>r)return ; if(L>=l&&R<=r) { if(A[k].ma>ma) { ma=A[k].ma; xx=A[k].x; } return ; } int mid=(L+R)>>1; _query(l,r,L,mid,A[k].c[0]); _query(l,r,mid+1,R,A[k].c[1]); } int query(int l,int r) { ma=-0x3f3f3f3f3f3f3f3f; _query(l,r,0,n,root); return xx; }}T1,T2;LL S1[MAXN*2];LL S2[MAXN*2];int main (){ int n,m,s,l,r; LL h; scanf("%d %d",&n,&m); s=n<<1; for(int i=1;i<=n;i++) { scanf("%lld",S1+i); } for(int i=n+1,t=1;i<s;i++,t++) S1[i]=S1[t]; for(int i=1;i<s;i++) S1[i]+=S1[i-1]; for(int i=0;i<s;i++) S2[i]=S1[i]; for(int i=0;i<n;i++) { scanf("%lld",&h); h=h<<1; S1[i]+=h; S2[i]-=h; S1[i+n]+=h; S2[i+n]-=h; } T1.n=s-1; T2.n=s-1; for(int i=0;i<s;i++) { T1.insert(i,S1[i]); T2.insert(i,-S2[i]); } while(m--) { scanf("%d %d",&l,&r); l--; r--; if(l<=r) { int u=r+1; r=n+l-1; l=u; } else { swap(l,r); l++; r--; } int ma=T1.query(l,r); int mi=T2.query(l,r); if(ma==mi) { int ma1=-1; if(ma>l) ma1=T1.query(l,ma-1); if(ma<r) { int u=T1.query(ma+1,r); if(ma1==-1||S1[ma1]<S1[u])ma1=u; } LL ans1=S1[ma1]-S2[mi]; int mi1=-1; if(mi>l) mi1=T2.query(l,mi-1); if(mi<r) { int u=T2.query(mi+1,r); if(mi1==-1||(-S2[mi1])<(-S2[u]))mi1=u; } LL ans2=S1[ma]-S2[mi1]; printf("%lld\n",max(ans1,ans2)); } else printf("%lld\n",S1[ma]-S2[mi]); } return 0;}
阅读全文
0 0
- 51nod 1593 公园晨跑
- 51Nod-1593-公园晨跑
- 51Nod
- 51Nod
- 51nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 剑指Offer_面试题01_赋值运算符函数
- 湖南省第六届程序设计竞赛---数字整除
- 套接字网络编程基础(一)
- Mongodb文档的查询操作
- ROS机器人操作系统的安装、配置与初级教程 18
- 51nod 1593 公园晨跑
- Logger的用法
- Request和Response
- ROS机器人操作系统的安装、配置与初级教程 19
- /var空间满了,简单处理一下
- 数据分析(入门篇)-第三章-Show出你的数据-Part1(地图)
- 题目:输入两棵二叉树A和B,判断B是不是A的子结构。
- AnroidUI 底部导航
- 图邻接链表c语言实现 graph_adj_link.cpp