也想了有半天,没有做出来……实际上做法确实也是十分精妙的。这里推荐一个blog,个人认为这位博主讲得挺好了:Sengxian's Blog;

  感觉启示是:首先要加强对莫队算法 & ST表的熟练程度。 在想与数列有关的问题的时候,要尽量多在草稿纸上手玩几组数据,观察其中的联系,应该可以观察到许多有用的性质。

  不过这题还有一个地方:网上的题解基本上都是先移动了右指针,后移动左指针;如果反过来,竟然被卡到只有10分。具体的原因我也不知道,但我猜想是不是由于r 和 l 的左右颠倒导致程序出现了一些问题,所以特判了一下,保证左指针永远在右指针的左侧。

#include <bits/stdc++.h>
using namespace std;
#define maxn 200000
#define int long long
int n, q, B = 316, a[maxn];
int ans, Ans[maxn];
int top, S[maxn], Log[maxn];
int LS[maxn], RS[maxn]; struct ques
{
    int l, r, id, bel;
    ques(int L = 0, int R = 0, int idx = 0)
    { l = L, r = R, id = idx, bel = (l / B) + 1; }
    bool operator < (const ques &q)
    const{
        return (bel < q.bel || (bel == q.bel && r < q.r));
    }
}Q[maxn]; int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * k;
} namespace RMQ
{
    int ST[maxn][20];
    int cmp(const int &i, const int &j) { return a[i] < a[j] ? i : j; }
    void Work()
    {
        for(int i = 2; i <= n; i ++) Log[i] = Log[i >> 1] + 1;
        for(int i = 1; i <= n; i ++) ST[i][0] = i;
        for(int j = 1, k = 1 << j; k <= n; j ++, k = 1 << j)
            for(int i = 1; k + i - 1 <= n; i ++)
                ST[i][j] = cmp(ST[i][j - 1], ST[i + (k >> 1)][j - 1]);
    }
    
    int Get_min(int l, int r)
    {
        int k = Log[r - l + 1];
        return cmp(ST[l][k], ST[r - (1 << k) + 1][k]);
    }
} void Get_Sum(int *LS)
{
    S[top = 0] = 0;
    for(int i = 1; i <= n; i ++)
    {
        while(top && a[S[top]] >= a[i]) top --;
        LS[i] = LS[S[top]] + (i - S[top]) * a[i];
        S[++ top] = i;
    }
} int Go_Right(int l, int r)
{
    int pos = RMQ :: Get_min(l, r);
    return (pos - l + 1) * a[pos] + LS[r] - LS[pos];
} int Go_Left(int l, int r)
{
    int pos = RMQ :: Get_min(l, r);
    return (r - pos + 1) * a[pos] + RS[l] - RS[pos];
} signed main()
{
    n = read(), q = read(), B = sqrt(n) + 1;
    for(int i = 1; i <= n; i ++) a[i] = read();
    RMQ :: Work();
    for(int i = 1; i <= q; i ++)
    {
        int x = read(), y = read();
        Q[i] = ques(x, y, i);
    }
    sort(Q + 1, Q + 1 + q);
    a[0] = -2e9; Get_Sum(LS); reverse(a + 1, a + 1 + n);
    Get_Sum(RS); reverse(a + 1, a + 1 + n);
    reverse(RS + 1, RS + 1 + n);
    int l = 1, r = 1; ans = a[1];
    for(int i = 1; i <= q; i ++)
    {
        if(Q[i].l > r)
        {
            while(r < Q[i].r) ans += Go_Right(l, r + 1), r ++;
            while(r > Q[i].r) ans -= Go_Right(l, r), r --;    
            while(l < Q[i].l) ans -= Go_Left(l, r), l ++;
            while(l > Q[i].l) ans += Go_Left(l - 1, r), l --;
        }
        else
        {
            while(l < Q[i].l) ans -= Go_Left(l, r), l ++;
            while(l > Q[i].l) ans += Go_Left(l - 1, r), l --;
            while(r < Q[i].r) ans += Go_Right(l, r + 1), r ++;
            while(r > Q[i].r) ans -= Go_Right(l, r), r --;    
        }
        Ans[Q[i].id] = ans;
    }
    for(int i = 1; i <= q; i ++) printf("%lld\n", Ans[i]);
    return 0;
}

【题解】HNOI2016序列的更多相关文章

  1. 题解-[HNOI2016]序列

    题解-[HNOI2016]序列 [HNOI2016]序列 给定 \(n\) 和 \(m\) 以及序列 \(a\{n\}\).有 \(m\) 次询问,每次给定区间 \([l,r]\in[1,n]\),求 ...

  2. 【LG3246】[HNOI2016]序列

    [LG3246][HNOI2016]序列 题面 洛谷 题解 60pts 对于每个位置\(i\),单调栈维护它往左第一个小于等于它的位置\(lp_i\)以及往右第一个小于它的位置\(rp_i\). 那么 ...

  3. [BZOJ4540][HNOI2016]序列 莫队

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...

  4. 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈

    [BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...

  5. BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]

    4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...

  6. 4540: [Hnoi2016]序列

    4540: [Hnoi2016]序列 https://www.lydsy.com/JudgeOnline/problem.php?id=4540 分析: 莫队+RMQ+单调栈. 考虑加入一个点后,区间 ...

  7. BZOJ4540 Hnoi2016 序列 【莫队+RMQ+单调栈预处理】*

    BZOJ4540 Hnoi2016 序列 Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- ...

  8. [Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1567  Solved: 718[Submit][Status] ...

  9. [HNOI2016]序列 CDQ+DP

    [HNOI2016]序列 CDQ 链接 loj 思路 一个点最小变为l,最大变为r,不变的时候为v 那么j能在i前面就要满足. \(j<i\) \(r[j]<=v[i]\) \(v[j]& ...

  10. P6604 [HNOI2016]序列 加强版

    *I. P6604 [HNOI2016]序列 加强版 摘自学习笔记 简单树论 笛卡尔树部分例题 I. 和 P6503 比较类似.我们设 \(f_i\) 表示全局以 \(i\) 结尾的子区间的最小值之和 ...

随机推荐

  1. web之前端获取上传图片并展示

    1.html中经常存在图片上传的问题,但是后续的展示基本上是通过后台输出流的方式来呈现的.但是这样耗费的资源比较多.所以这里学习了一种前端直接展示图片的方式(供参考). 2.html的编写方式比较简单 ...

  2. 使用conlleval.pl对CRF测试结果进行评价的方法

    基于CRF做命名实体识别系列 用CRF做命名实体识别(一) 用CRF做命名实体识别(二) 用CRF做命名实体识别(三) 评测 用CRF做完命名实体识别我们测试之后得到的结果就是预测的标签,并不能直接得 ...

  3. mysql表的核心元数据

    索引的 mysql> show indexes from recordsInRangeTest; +--------------------+------------+------------- ...

  4. 【selenium】selenium全分享

    第一节:selenium基础 [http://note.youdao.com/noteshare?id=43603fb53593bfc15c28bc358a3fa6ec] 目录: selenium简介 ...

  5. GIt学习第二天之版本回退、工作区和暂存区

    搬运自 ‘廖雪峰的官方网站’ 地址:https://www.liaoxuefeng.com/ 1.版本回退 在Git中,我们用git log命令显示从最近到最远的提交日志,如果嫌输出信息太多,看得眼花 ...

  6. Angular6项目搭建

    参照 草根专栏- ASP.NET Core + Ng6 实战:https://v.qq.com/x/page/b076702elvw.html 安装工具: Nodejs, npm     最新版, h ...

  7. JDK源码分析:Integer.java部分源码解析

    1)声明部: public final class Integer extends Number implements Comparable<Integer> extends Number ...

  8. 贪心算法——Huffman 压缩编码的实现

    1. 如何理解 "贪心算法" 假设我们有一个可以容纳 100 Kg 物品的背包,可以装各种物品.我们有以下 5 种豆子,每种豆子的总量和总价值都各不相同.怎样装才能让背包里豆子的总 ...

  9. 团队Beta阶段事后分析

    团队Beta阶段事后分析 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件要解决用户的休闲娱乐问题,为用户提供好玩的模拟经营类的游戏,游戏主题 ...

  10. JavaScript初探系列之String的基本操作

    1.字符串转换 字符串转换是最基础的要求和工作,你可以将任何类型的数据都转换为字符串,你可以用下面三种方法的任何一种: var myStr = num.toString(); // "19& ...