1272 最大距离 只想到了dp

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1272

离散化后,用dp[i]表示向右,大于等于i这个数字的最大位置

dp[i] = max(dp[i + 1], dp[i])

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 50000 + 20;
int a[maxn], dp[maxn], id[maxn];
int n;
vector<int>da;
void work() {
    scanf("%d", &n);
    int top = 0;
    da.push_back(0);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        da.push_back(a[i]);
    }
    sort(da.begin(), da.end());
    for (int i = 1; i <= n; ++i) {
        id[i] = lower_bound(da.begin(), da.end(), a[i]) - da.begin();
    }
    for (int i = n; i >= 1; --i) {
        dp[id[i]] = max(dp[id[i]], i);
    }
//    for (int i = 1; i <= n; ++i) {
//        cout << id[i] << " ";
//    }
    for (int i = n; i >= 1; --i) {
        dp[i] = max(dp[i], dp[i + 1]);
    }
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        ans = max(ans, dp[id[i]] - i);
    }
    cout << ans << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}

然后这题排个序,然后记录下最小的id就好。

把思维转过来,每个i,去右边找,相当于每个i,向左边找,一样的。

时间: 2024-10-12 03:06:26

1272 最大距离 只想到了dp的相关文章

留只脚印(DP)

题目链接:http://codeforces.com/problemset/problem/698/A 很久很久没做咯~~~~ dp 是个很神奇的东西.... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 const int max_day = 100 + 5; 8 const int

51nod 1272 最大距离

题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 给出一个长度为N的整数数组A,对于每一个数组元素,如果他后面存在大于等于该元素的数,则这两个数可以组成一对.每个元素和自己也可以组成一对.例如:{5, 3, 6, 3, 4, 2},可以组成11对,如下(数字为下标): (0,0), (0, 2), (1, 1), (1, 2), (1, 3), (1, 4), (2, 2), (3, 3), (3, 4), (4,

51Nod 1272最大距离 (树状数组维护前缀最小值)

题目链接 最大距离 其实主流解法应该是单调栈--我用了树状数组. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 7 const int N = 100010; 8 9 struct node{ 10 int x, y; 11 friend bool operator < (const node &a, c

悬线法——有套路的DP

例题 P1169 [ZJOI2007]棋盘制作 题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8×88 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则. 小Q找到了一张由N×MN \times MN×M个正方形的格子组成的矩形纸片,每个

DP总结 ——QPH

常见优化 单调队列 形式 dp[i]=min{f(k)} dp[i]=max{f(k)} 要求 f(k)是关于k的函数 k的范围和i有关 转移方法 维护一个单调递增(减)的队列,可以在两头弹出元素,一头压入元素. 队列中维护的是两个值.一个是位置,这和k的范围有关系,另外一个是f(k)的值,这个用来维护单调性,当然如果f(k)的值可以利用dp值在O(1)的时间内计算出来的话队列中可以只维护一个表示位置的变量. 枚举到一个i的时候,首先判断队首元素的位置是否已经不满足k的范围了,如果不满足就将队首

ZOJ3791 An Easy Game(DP)

给两个长n的01串s1和s2,要对s1进行k次修改,每次修改m个不同位置,问有几种方式修改成s2. 想偏了,只想到原始的01数值是不重要的,因为每个位置修改次数的奇偶性是确定的这一层.. 其实,这题只要关心从起点到终点有几个位置是不同的,一个数值足矣. 然后具体的状态就是:dp[i][j]表示,进行i次修改后有j个位置不同的方案数. 转移用我为人人,dp[i][j]通过选择修改a个位置不同.m-a个位置相同转移到dp[i+1][j-(a-(m-a))],即dp[i+1][j-(a-(m-a))]

POJ 3666 Making the Grade [DP]

题意: 给定一个序列,以最小代价将其变成单调不增或单调不减序列,这里的代价看题目公式. 思路: 很容易想到是DP. 1. 对前i个序列,构成的最优解其实就是与两个参数有关.一个是这个序列处理后的最大值mx,和这个序列处理的代价值cost. 显然最大值mx最小最好(这样第i+1个值可以不花代价直接接在其后面的可能性更大),cost最小也最好(题意要求),但是两者往往是鱼和熊掌. 用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost. 所以状态转移方

hdu 5791 思维dp

题目描述: 求序列A,B的公共子序列个数: 基本思路: 想到了dp,选的状态也对,但是就是就是写不出状态转移方程,然后他们都出了,到最后我还是没出,很难受,然后主要是没有仔细考虑dp[i][j],dp[i][j-1],dp[i-1][j],dp[i-1][j-1]在A[ i]和B[i]在相同和不相同是的数量关系,我为啥就没想到要减呢,只想着怎么把他们加起来,着实智障: 定义状态dp[i][j]为序列A扫到i,序列B扫到B时候的公共子序列个数,状态转移方程如下: 其实这个状态转移方程也没那么好证明

HDU2167 Pebbles(状压DP)

题目给一张n×n的格子,每个格子都有数字,要从格子中取若干个数字,八个方向相邻的数字不能一起取,问取的数字最大和是多少. 从第一行一行一行看下去,可以发现第1行取哪几列只会影响到第2行,第3行后面的一点影响都没有.即第i行的决策只受i-1行决策的影响. 那么自然想到状态DP—— dp[i][S]前i行其中第i行取的列的集合是S的取数最大和 dp[i][S]=max(dp[i-1][S'])+集合S数字和(S是S'的合法的下一行的取法) 虽然题目n最多15,集合S就215种状态,但事实上合法的(不