HDU 6047 Maximum Sequence (贪心+单调队列)

题意:给定一个序列,让你构造出一个序列,满足条件,且最大。条件是 选取一个ai <= max{a[b[j], j]-j}

析:贪心,贪心策略就是先尽量产生大的,所以就是对于B序列尽量从头开始,由于数据比较大,采用桶排序,然后维护一个单调队列,使得最头上最大。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 250000 + 10;
const LL mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
  return r > 0 && r <= n && c > 0 && c <= m;
}

int num[maxn];
int a[maxn<<1];
int q[maxn<<1];

int main(){
  while(scanf("%d", &n) == 1){
    memset(num, 0, sizeof num);
    for(int i = 1; i <= n; ++i)  scanf("%d", a+i);
    for(int i = 0; i < n; ++i){
      scanf("%d", &m);
      ++num[m];
    }

    int fro = 0, rear = 0;
    q[++rear] = 1;
    for(int i = 2; i <= n; ++i){
      while(rear > fro && a[i] - i >= a[q[rear]] - q[rear])  --rear;
      q[++rear] = i;
    }
    int cnt = 1;
    for(int i = n+1; i <= n+n; ++i){
      while(!num[cnt]) ++cnt;
      --num[cnt];
      while(q[fro+1] < cnt)  ++fro;
      a[i] = a[q[fro+1]] - q[fro+1];
      while(rear > fro && a[i] - i >= a[q[rear]] - q[rear])  --rear;
      q[++rear] = i;
    }

    int ans = 0;
    for(int i = n+1; i <= n+n; ++i)  ans = (ans + a[i]) % mod;
    printf("%d\n", ans);
  }
  return 0;
}

  

时间: 2024-10-27 07:49:08

HDU 6047 Maximum Sequence (贪心+单调队列)的相关文章

HDU 6047 Maximum Sequence(贪心+线段树)

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6047 题目: Maximum Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 90    Accepted Submission(s): 44 Problem Description Steph is extremely o

hdu 6047 Maximum Sequence(贪心)

Description Steph is extremely obsessed with "sequence problems" that are usually seen on magazines: Given the sequence 11, 23, 30, 35, what is the next number? Steph always finds them too easy for such a genius like himself until one day Klay c

【多校训练2】HDU 6047 Maximum Sequence

http://acm.hdu.edu.cn/showproblem.php?pid=6047 [题意] 给定两个长度为n的序列a和b,现在要通过一定的规则找到可行的a_n+1.....a_2n,求sum{a_n+1.....a_2n}的最大值 每次从序列b中选择一个数bk,那么构造的ai就是max{aj -j},其中bk<=j<i 每个bk最多用一次 [思路] 首先我们需要的是aj-j 可以贪心,即对于当前要构造的数ai,尽可能找bk使得能够取得最大的aj-j 线段树区间查询最优值+单点更新

HDU 5014 Number Sequence 贪心 2014 ACM/ICPC Asia Regional Xi&#39;an Online

尽可能凑2^x-1 #include <cstdio> #include <cstring> const int N = 100005; int a[N], p[N]; int init(int x) { int cnt = 0; while(x > 1) { x /= 2; cnt ++; } return cnt + 1; } int main() { int n; while(~scanf("%d", &n)){ for(int i = 0;

POJ 3017 Cut the Sequence (单调队列优化DP)

POJ 3017 Cut the Sequence (单调队列优化DP) ACM 题目地址: POJ 3017 Cut the Sequence 题意: 将一个由N个数组成的序列划分成若干段,要求每段数字的和不超过M,求[每段的最大值]的和 的最小的划分方法,输出这个最小的和. 分析: 方程是:dp[i] = min(dp[j]+maxsum[j+1][i]) 但复杂度n*n太高,需要优化. 可以用单调队列+BST优化,其实只需要维护每一段的最大值. 看了这篇题解的:http://blog.cs

hdu 4915 Parenthese sequence (贪心+模拟)

题目大意: 一个序列中有左括号和右括号,还有问号,问号可以任意转换成左右括号. 问这个序列有多少种情况的转变使得这个序列变成合法的括号匹配序列. 思路分析: 首先我们分析一下,如何使得一个序列是合法的括号匹配序列. 我们很容易想到的是用栈模拟匹配过程. 当遇到左括号就进栈,当遇到右括号就让栈顶的左括号出栈. 那么在模拟的过程中,造成这个序列的不合法的原因只有当右括号来的时候,此时的栈已经为空. 这里补充一句,一旦一个序列给定,那么这里面的问号有多少变成左括号,多少变成右括号,是一定的. 看完以上

hdu 5014 Number Sequence(贪心)

题目链接:hdu 5014 Number Sequence 题目大意:给定n,表示有0~n这n+1个数组成的序列a,要求构造一个序列b,同样是由0~n组成,要求∑ai⊕bi尽量大. 解题思路:贪心构造,对于n来说,找到n对应二进制的取反对应的数x,那么从x~n之间的数即可两两对应,然后x-1即是一个子问题. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; con

BZOJ 2424 订货(贪心+单调队列)

怎么题解都是用费用流做的啊...用单调队列多优美啊. 题意:某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费.假设仓库容量为S. 首先这道题和经典的汽车加油问题差不多,那道题可以用单调队列做,然而这道题也是可以的. 此题唯一的难点在于存储费用m,也

HDU Non-negative Partial Sums (单调队列)

Problem Description You are given a sequence of n numbers a0,..., an-1. A cyclic shift by k positions (0<=k<=n-1) results in the following sequence: ak ak+1,..., an-1, a0, a1,..., ak-1. How many of the n cyclic shifts satisfy the condition that the