51nod1593 公園晨跑

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");
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章