• HDU 4521 小明系列问题——小明序列【dp+线段树优化||最长递增序列】


    小明系列问题——小明序列

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 3361    Accepted Submission(s): 1058


    Problem Description
      大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了。可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找去都是自己早已研究过的序列。小明想既然找不到,那就自己来发明一个新的序列问题吧!小明想啊想,终于想出了一个新的序列问题,他欣喜若狂,因为是自己想出来的,于是将其新序列问题命名为“小明序列”。

      提起小明序列,他给出的定义是这样的:
      ①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 ;
      ②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ... , Aim },m为元素个数 ;
      ③其中Sub满足 Ai1 < Ai2 < Ai3 < ... < Aij-1 < Aij < Aij+1 < ... < Aim ;
      ④同时Sub满足对于任意相连的两个Aij-1与Aij都有 ij - ij-1 > d (1 < j <= m, d为给定的整数);
      ⑤显然满足这样的Sub子序列会有许许多多,而在取出的这些子序列Sub中,元素个数最多的称为“小明序列”(即m最大的一个Sub子序列)。
      例如:序列S={2,1,3,4} ,其中d=1;
      可得“小明序列”的m=2。即Sub={2,3}或者{2,4}或者{1,4}都是“小明序列”。

      当小明发明了“小明序列”那一刻,情绪非常激动,以至于头脑凌乱,于是他想请你来帮他算算在给定的S序列以及整数d的情况下,“小明序列”中的元素需要多少个呢?
     

    Input
      输入数据多组,处理到文件结束;
      输入的第一行为两个正整数 n 和 d;(1<=n<=10^5 , 0<=d<=10^5)
      输入的第二行为n个整数A1 , A2 , A3 , ... , An,表示S序列的n个元素。(0<=Ai<=10^5)
     

    Output
      请对每组数据输出“小明序列”中的元素需要多少个,每组测试数据输出一行。
     

    Sample Input
    2 0 1 2 5 1 3 4 5 1 2 5 2 3 4 5 1 2
     

    Sample Output
    2 2 1
     

    Source

    第一种解法:dp+线段树优化

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    #include <cmath>  
    #include <queue>  
    #include <string>  
    #include <map>  
    #include <cstring>  
    #define INF 0x3f3f3f3f  
    #define ms(x,y) memset(x,y,sizeof(x))  
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    
    const int maxn = 110000;
    const int mod = 998244353;
    
    #define lson l,m,rt<<1  
    #define rson m+1,r,rt<<1|1  
    #define lz 2*u,l,mid
    #define rz 2*u+1,mid+1,r
    
    int a[maxn + 5], dp[maxn + 5];
    int sum[maxn << 2];
    
    void update(int pos, int c, int l, int r, int rt)
    {
    	sum[rt] = max(sum[rt], c);
    	if (l == r) return;
    	int m = (l + r) >> 1;
    	if (pos <= m) update(pos, c, lson);
    	else update(pos, c, rson);
    }
    
    int query(int L, int R, int l, int r, int rt)
    {
    	if (L > R) return 0;
    	if (L <= l && R >= r)
    	{
    		return sum[rt];
    	}
    	int m = (l + r) >> 1;
    	int ret = 0;
    	if (L <= m) ret = query(L, R, lson);
    	if (R > m) ret = max(ret, query(L, R, rson));
    	return ret;
    }
    
    
    int main()
    {
    	int n, d;
    	while (~scanf("%d%d", &n, &d))
    	{
    		ms(sum, 0);
    		for (int i = 1; i <= n; i++)
    			scanf("%d", &a[i]);
    
    		int ans = 0;
    
    		for (int i = 1; i <= n; i++)
    		{
    			if (i - d - 1>= 1)
    				update(a[i - d - 1] + 1, dp[i - d - 1], 1, maxn, 1);	//因为相隔大于d所以为i-d-1因为a[i]>a[i-1]所以要加1
    			dp[i] = query(1, a[i], 1, maxn, 1) + 1;
    			ans = max(ans, dp[i]);
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    


    第二种解法:dp的优化

    (未完待续)

    Fighting~
  • 相关阅读:
    UIView背景渐变三种方法
    Phone漂亮的动画
    图片处理代码片段
    UIProgressView进度条
    UIActivityIndicatorView
    NSTimer定时器类
    iPhone Tableview分批显示数据
    无限剑制
    兔子繁殖(easy)
    植树节
  • 原文地址:https://www.cnblogs.com/Archger/p/12774723.html
Copyright © 2020-2023  润新知