题意特难懂,我看了好多遍,最后还是看讨论版里别人的问答,才搞明白题意,真是汗。

其实题目等价于给n个点,这n个点均匀分布在一个圆上(知道圆半径),点与点之间的路程(弧长)已知,点是有权值的,已知,点与点的距离等于其最短路程(弧长)加上两点的权值,问距离最远的两个点的下标。

因为是环状,不好处理,所以我在输入的时候就简单处理了一下,使问题变成直线上的等价问题了。做法就是在输入序列后面再加上前半段序列,例如样例5 2 1 10 1 10 10,可以处理成1 10 1 10 10 1 10,这样就只需要顺序处理了,不过最后输成的下标是需要处理的,因为要求的是字典序最小的下标对。

变成直线后的问题就比较简单了。便于理解的做法是维护一个长度为半圆的队列,当处理i时,把队列里的点和i点比较,更新最值,然后i入队,队列头元素出队。这是n^2的效率,换成单调队列,就能过了。不过,我是用优先队列做的,代码比用单调队列稍复杂一丁点,也是脑子木了,还没打完,金牛就把我代码要了去用单调队列接着打了。先贴上金牛的单调队列的代码,再贴我的,都是1a:

/*
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <functional>
#include <numeric>
#include <cctype>
using namespace std; #define D(x) typedef long long LL;
const int MAXN = ; int R, N;
LL m;
int data[MAXN];
LL ans;
int ansi, ansj; void update(LL a, LL b)
{
LL temp = (b - a) * R + data[a] + data[b];
a %= N - m;
b %= N - m;
if (a > b)
swap(a, b);
if (temp > ans)
{
D(printf("a %lld b %lld\n", a, b));
ans = temp;
ansi = a;
ansj = b;
return;
}
if (temp < ans)
return;
if (ans == )
if (ansi > a || (ansi == a && ansj > b))
{
ansi = a;
ansj = b;
return;
}
} LL work() { deque<LL> q;
q.push_back();
long long cur_pos = ;
long long ret = ;
for (int i = ; i < N; i++)
{
cur_pos += R;
while (!q.empty() && q.front() < i - m)
q.pop_front();
update(q.front(), i);
while (!q.empty() && (i - q.back()) * R + data[q.back()] < data[i])
q.pop_back();
q.push_back(i);
}
return ret;
} int main() {
int T;
scanf("%d", &T);
for (int t = ; t <= T; t++) {
scanf("%d %d", &N, &R);
for (int i = ; i < N; i++) {
scanf("%d", &data[i]);
}
m = N / ;
for (int i = ; i < m; i++) {
data[i + N] = data[i];
}
N += m;
ans = ;
work();
printf("Case #%d\n%d %d\n", t, ansi + , ansj + );
}
return ;
}

下面是我的优先队列的:

/*
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <functional>
#include <numeric>
#include <cctype>
using namespace std;
typedef long long LL;
const int MAXN = ;
typedef struct Mont {
int height;
int index;
LL value;
Mont(int ii = , int hh = , LL vv = ) {
height = hh;
index = ii;
value = vv;
}
} Mont;
bool inline operator<(const Mont& m1, const Mont& m2) {
return m1.value < m2.value;
}
LL R;
int N, m;
int data[MAXN];
LL ans;
int ansi, ansj; inline void treat(int &i, int &j) {
if (i >= N - m) {
i = i % (N - m);
}
if (j >= N - m) {
j = j % (N - m);
}
if (i > j) {
int t = i;
i = j;
j = t;
}
} void work() {
priority_queue<Mont> mont;
mont.push(Mont(, data[], data[]));
for (int i = ; i < N; i++) {
while (mont.top().index < (i - m)) {
mont.pop();
}
Mont topm = mont.top();
LL tans = (i - topm.index) * R + data[i] + data[topm.index];
if (tans > ans) {
ans = tans;
ansi = topm.index;
ansj = i;
treat(ansi, ansj);
} else if(tans == ans) {
int x = topm.index;
int y = i;
treat(x, y);
if (x < ansi || (x == ansi && y < ansj)) {
ansi = x;
ansj = y;
}
}
mont.push(Mont(i, data[i], data[i] - i * R));
}
} int main() {
int T;
scanf("%d", &T);
for (int t = ; t <= T; t++) {
scanf("%d %lld", &N, &R);
for (int i = ; i < N; i++) {
scanf("%d", &data[i]);
}
m = N / ;
for (int i = ; i < m; i++) {
data[i + N] = data[i];
}
N += m;
ans = ;
work();
printf("Case #%d:\n%d %d\n", t, ansi + , ansj + );
}
return ;
}

hdu5261单调队列的更多相关文章

  1. BestCoder Round #89 B题---Fxx and game(单调队列)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5945     问题描述 输入描述 输出描述 输入样例 输出样例 题意:中文题,不再赘述: 思路:  B ...

  2. 单调队列 && 斜率优化dp 专题

    首先得讲一下单调队列,顾名思义,单调队列就是队列中的每个元素具有单调性,如果是单调递增队列,那么每个元素都是单调递增的,反正,亦然. 那么如何对单调队列进行操作呢? 是这样的:对于单调队列而言,队首和 ...

  3. FZU 1914 单调队列

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=1914 题意: 给出一个数列,如果它的前i(1<=i<=n)项和都是正的,那么这个数列是正的,问这个 ...

  4. BZOJ 1047 二维单调队列

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047 题意:见中文题面 思路:该题是求二维的子矩阵的最大值与最小值的差值尽量小.所以可以考 ...

  5. 【BZOJ3314】 [Usaco2013 Nov]Crowded Cows 单调队列

    第一次写单调队列太垃圾... 左右各扫一遍即可. #include <iostream> #include <cstdio> #include <cstring> ...

  6. BZOJ1047: [HAOI2007]理想的正方形 [单调队列]

    1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2857  Solved: 1560[Submit][St ...

  7. hdu 3401 单调队列优化DP

    Trade Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status ...

  8. 【转】单调队列优化DP

    转自 : http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列是一种严格单调的队列,可以单调递增,也可以单调递减.队 ...

  9. hdu3530 单调队列

    Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

随机推荐

  1. Linux System Programming 学习笔记(三) 标准缓冲I/O

    1. partial block operations are inefficient. The operating system has to “fix up” your I/O by ensuri ...

  2. Java-Pi的几种实现

    1.无穷级数计算 p = 1 - 1/3 + 1/5 -1/7+..... π=4p 2.使用 Nilakantha 级数 π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7 ...

  3. UVa11021 Tribles

    概率 递推 每只麻球都是独立计算的. 可以递推,设f[i]表示一只麻球经过i天死光的概率,那么f[i]的k次方就是k只麻球经过i天死光的概率. 则f[i]=p[0]+p[1]*f[i-1]^1+p[2 ...

  4. 洛谷 P 1387 最大正方形

    题目描述 在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长. 输入输出格式 输入格式: 输入文件第一行为两个整数n,m(1<=n,m<=100),接下来n行,每行m ...

  5. xml文档绑定某个属性值到treeview算法

    原文发布时间为:2008-08-10 -- 来源于本人的百度文章 [由搬家工具导入] using System.Xml; protected void Button2_Click(object sen ...

  6. svn不是内部或外部命令?

    svn不是内部或外部命令? 我的系统是Win7, [计算机]-->右键[属性]-->[高级系统设置]-->[环境变量]-->[系统变量 (S)]-->[Path]--&g ...

  7. yii使用bootstrap分页样式

    Bootstrap是Twitter推出的一个开源的用于前端开发的工具包.它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架.Bootstra ...

  8. 树(弱化版)(lca)

    3306: 树 时间限制: 10 Sec  内存限制: 256 MB 题目描述 给定一棵大小为 n 的有根点权树,支持以下操作:  • 换根  • 修改点权      • 查询子树最小值 输入 第一行 ...

  9. GRPC协议的相关原理

    GRPC的Client与Server,均通过Netty Channel作为数据通信,序列化.反序列化则使用Protobuf,每个请求都将被封装成HTTP2的Stream,在整个生命周期中,客户端Cha ...

  10. HDU4372 Buildings

    @(HDU)[Stirling數, 排列組合] Problem Description There are N buildings standing in a straight line in the ...