51Nod-1593-公园晨跑

228 篇文章 1 订阅
75 篇文章 0 订阅

ACM模版

描述

描述

题解

十分有趣的一个问题,用到线段树了……

我学姐写这个题解十分的详细,我想我一定不会写的更详细,所以直接给大家一个我学姐的博客吧,可以去哪儿看一下题解……但是学姐的线段树写得真让人感觉不习惯,所以我自己只贴一下代码吧!

>>>佐理慧的 blog<<< 点赞点赞点赞!!!

代码

#include <stdio.h>
#include <algorithm>
#include <string.h>

#define lson rt << 1
#define rson rt << 1 | 1

using namespace std;

typedef long long ll;

const int MAXN = 3e5 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;

struct point
{
    int pos;
    ll mx;

    point()
    {
        mx = -INF;
    }
};

struct Seg
{
    int root, pos, n;
    ll mx, key;
    point A[MAXN << 3];

    Seg()
    {
        root = 1;
    }

    void push_up(point &a, int rt)
    {
        if (A[lson].mx > A[rson].mx)
        {
            a.mx = A[lson].mx;
            a.pos = A[lson].pos;
        }
        else
        {
            a.mx = A[rson].mx;
            a.pos = A[rson].pos;
        }
    }

    void update(int x, int l, int r, int rt)
    {
        if (x > r || x < l)
        {
            return ;
        }
        if (l == r)
        {
            A[rt].mx = key;
            A[rt].pos = x;
            return ;
        }
        int m = (l + r) >> 1;
        update(x, l, m, lson);
        update(x, m + 1, r, rson);
        push_up(A[rt], rt);
    }
    void update(int x, ll k)
    {
        key = k;
        update(x, 0, n, root);
    }

    void query(int l, int r, int L, int R, int rt)
    {
        if (R < l || L > r)
        {
            return ;
        }
        if (L >= l && R <= r)
        {
            if (A[rt].mx > mx)
            {
                mx = A[rt].mx;
                pos = A[rt].pos;
            }
            return ;
        }
        int M = (L + R) >> 1;
        query(l, r, L, M, lson);
        query(l, r, M + 1, R, rson);
    }

    int query(int l, int r)
    {
        mx = -INF;
        query(l, r, 0, n, root);
        return pos;
    }
} segA, segB;

ll A[MAXN << 1];
ll B[MAXN << 1];

int n, m;
ll h;

template <class T>
inline void scan_d(T &ret)
{
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}

template <class T>
inline void print_d(T x)
{
    if (x > 9)
    {
        print_d(x / 10);
    }
    putchar(x % 10 + '0');
}

int main ()
{
    scan_d(n), scan_d(m);
    int len = n << 1;
    for (int i = 1; i <= n; i++)
    {
        scan_d(A[i]);
        A[i + n] = A[i];
    }
    for (int i = 1; i < len; i++)
    {
        A[i] += A[i - 1];
    }
    memcpy(B, A, sizeof(A));

    for (int i = 0; i < n; i++)
    {
        scan_d(h);
        h = h << 1;
        A[i] += h;
        B[i] -= h;
        A[i + n] += h;
        B[i + n] -= h;
    }

    segA.n = len - 1;
    segB.n = len - 1;
    for (int i = 0; i < len; i++)
    {
        segA.update(i, A[i]);
        segB.update(i, -B[i]);
    }

    int l, r;
    while (m--)
    {
        scan_d(l), scan_d(r);
        l--;
        r--;
        if (l <= r)
        {
            int tmp = r + 1;
            r = n + l - 1;
            l = tmp;
        }
        else
        {
            swap(l, r);
            l++;
            r--;
        }

        int mx = segA.query(l, r);
        int mn = segB.query(l, r);
        if (mx == mn)
        {
            int tmp = -1, tmp_;
            if (mx > l)
            {
                tmp = segA.query(l, mx - 1);
            }
            if (mx < r)
            {
                tmp_ = segA.query(mx + 1, r);
                if (tmp == -1|| A[tmp] < A[tmp_])
                {
                    tmp = tmp_;
                }
            }
            ll ans1 = A[tmp] - B[mn];

            tmp = -1;
            if (mn > l)
            {
                tmp = segB.query(l, mn - 1);
            }
            if (mn < r)
            {
                tmp_ = segB.query(mn + 1, r);
                if (tmp == -1 || B[tmp] > B[tmp_])
                {
                    tmp = tmp_;
                }
            }
            ll ans2 = A[mx] - B[tmp];
            print_d(max(ans1, ans2));
            putchar(10);
        }
        else
        {
            print_d(A[mx] - B[mn]);
            putchar(10);
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值