Description
有一隻猴子,他生活在一個環形的公園裏。有n棵樹圍繞着公園。第i棵樹和第i+1棵樹之間的距離是 di ,而第n棵樹和第一棵樹之間的距離是 dn 。第i棵樹的高度是 hi 。
這隻猴子每天要進行晨跑。晨跑的步驟如下:
· 他先選擇兩棵樹;
· 然後爬上第一棵樹;
· 再從第一棵樹上下來,接着圍繞着公園跑(有兩個可能的方向)到第二棵樹,然後爬上第二棵樹;
· 最後從第二棵樹上下來。
但是有一些小孩會在連續的一些樹上玩耍。所以猴子不能經過這些樹。
比如現在猴子選擇的第x棵和第y棵樹,那麼該早晨他消耗的能量是 2(hx+hy)+dist(x,y) 。由於某一條路徑是被小孩子佔據的,所以他只能跑另外一條,因此 dist(x,y) 是確定的。
現在給出第i天,孩子們會在第 ai 棵樹和 bi 棵樹之間玩耍。具體的,如果 ai≤bi ,那麼孩子玩耍的區間就是 [ai,bi] ,否則孩子玩耍的區間就是 [ai,n]⋃[1,bi] 。
請幫助這隻猴子找出兩棵樹,讓他晨跑的時候他能夠消耗最大的能量。
Input
單組測試數據。
第一行有兩個整數 n 和m (3≤n≤10^5, 1≤m≤10^5),表示樹的數目,以及猴子跑步的天數。
第二行有n個整數d1,d2,…,dn (1≤di≤10^9),表示樹之間的距離。
第三行有n個整數h1,h2,…,hn (1≤hi≤10^9),表示樹的高度。
接下來m行,第一行有兩個整數 ai和bi (1≤ai,bi≤n),描述每一天孩子玩耍的區間。輸入保證至少有兩個棵樹孩子不會進行玩耍,這樣猴子每天都可以晨跑了。
Output
對於每一天,輸出猴子消耗的最大能量。
Input示例
樣例輸入1
5 3
2 2 2 2 2
3 5 2 1 4
1 3
2 2
4 5
Output示例
樣例輸出1
12
16
18
Solution
環的情況比較難以處理 所以我們考慮拆環爲一個2n的鏈
然後我們把距離算出來,di表示第i號點到第一號點的距離
我們要求|dx-dy|+2(hx+hy)
令x
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define L rt<<1
#define R rt<<1|1
using namespace std;
const int N=100005;
const long long inf =-1234567891011;
typedef long long ll;
ll h,ans1,ans2,s1[N<<1],s2[N<<1],a[N<<1];
int n,m,i,s,l,r,u,ma1,ma,mi1,mi,t;
struct edge{
ll x; int y;
edge( ){
x=inf;
}
};
inline ll max(ll a,ll b) { return a>b?a:b;}
struct pp{
edge tr[N<<3];
inline void pushup(int rt){
if (tr[L].x>tr[R].x){
tr[rt].x=tr[L].x;
tr[rt].y=tr[L].y;}
else {
tr[rt].x=tr[R].x;
tr[rt].y=tr[R].y;
}
}
inline void insert(int rt,int x,int l,int r,ll y){
if (l==r) {
tr[rt].x=y;
tr[rt].y=x;
return;}
int mid=(l+r)>>1;
if (x<=mid) insert(L,x,l,mid,y);
else insert(R,x,mid+1,r,y);
pushup(rt);
}
inline edge merge(edge a,edge b){
edge p;
if (a.x>b.x) p.y=a.y; else p.y=b.y;
p.x=max(a.x,b.x);
return p;
}
edge query(int rt,int l,int r,int x,int y){
if (x<=l&&y>=r) return tr[rt];
int mid=(l+r)>>1;
edge p,w;
if (x<=mid) p=query(L,l,mid,x,y);
if (y>mid) w=query(R,mid+1,r,x,y);
p=merge(p,w);
return p;
}
} T1,T2;
ll read(){
ll sum=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();}
return sum;
}
int re(){
int sum=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();}
return sum;
}
void write(ll x)
{
if (x>9) write(x/10);
putchar(x%10+'0');
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d%d",&n,&m);
s=n<<1;
fo(i,1,n) scanf("%lld",&a[i]);
for(i=n+1,t=1;i<=s;i++,t++) a[i]=a[t];
fo(i,1,s) s1[i]=s1[i-1]+a[i-1],s2[i]=s1[i];
fo(i,1,n){
scanf("%lld",&h);
h<<=1;
s1[i]+=h,s2[i]-=h;
s1[i+n]+=h,s2[i+n]-=h;}
fo(i,1,s){
T1.insert(1,i,1,s,s1[i]);
T2.insert(1,i,1,s,-s2[i]);
}
while (m){
m--;
l=re(),r=re();
if (l<=r){
u=r+1;
r=n+l-1;
l=u;
} else {
r++,l--;
swap(l,r);
}
ma=T1.query(1,1,s,l,r).y;
mi=T2.query(1,1,s,l,r).y;
if (ma==mi){
ma1=-1;
if (ma>l) ma1=T1.query(1,1,s,l,ma-1).y;
if (ma<r){
u=T1.query(1,1,s,ma+1,r).y;
if (ma1==-1||s1[ma1]<s1[u]) ma1=u;}
mi1=-1;
if (mi>l) mi1=T2.query(1,1,s,l,mi-1).y;
if (mi<r) {
u=T2.query(1,1,s,mi+1,r).y;
if (mi1==-1||(-s2[mi1])<(-s2[u])) mi1=u;}
ans1=s1[ma1]-s2[mi],ans2=s1[ma]-s2[mi1];
write(max(ans1,ans2));
printf("\n");
} else {
write(s1[ma]-s2[mi]);
printf("\n");
}
}
}