HDU4521线段树

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


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

  提起小明序列,他给出的定义是这样的:
  ①首先定义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

老题。维护区间最值。

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) {
		new HDU4521().solve();
	}
}

class HDU4521 {

	InputReader in = new InputReader(System.in);
	PrintWriter out = new PrintWriter(System.out);

	final int N  = 100000 ;
	SegmentTree tree = new SegmentTree() ;
	int[] seq = new int[N+8] ;
	int[] dp = new int[N+8] ;

	void solve() {
		 int n , d ; 
		 while(in.hasNext()){
			 n = in.nextInt() ;
			 d = in.nextInt() ;
			 for(int i = 1 ; i <= n ; i++) seq[i] = in.nextInt() ;
			 
			 tree.build() ;
			 int res = 1 ;
			 for(int i = 1 ; i <= d+1 ; i++) dp[i] = 1 ;
			 for(int i = d+2 ; i <= n ; i++){
				 tree.update(seq[i-d-1] , dp[i-d-1] , 1 , 0 , N)  ;
				 dp[i] = tree.query(0 , seq[i]-1 , 1 , 0 , N) + 1 ;
				 res = Math.max(res , dp[i]) ;
			 }
			 out.println(res) ;
		 }
		
         out.flush() ;
	}
}

class SegmentTree{
	final int N = 100008 ;
	int[] max = new int[N<<2] ;
	
	void build(){
		Arrays.fill(max ,  0) ;
	}
	
	void update(int pos , int val , int root , int l , int r){
		if(l == r){
			max[root] = Math.max(max[root] , val) ;
			return ; 
		}
		int m = (l + r) >> 1 ;
	    if(pos <= m) update(pos, val, root<<1 , l , m) ;
	    else update(pos, val, root<<1|1 , m+1 , r) ;
	    max[root] = Math.max(max[root<<1] , max[root<<1|1]) ;
	}
	
	int query(int L , int R , int root , int l , int r){
		if(L > R) return 0 ;
		if(L <= l && r <= R) return max[root] ;
		int m = (l + r) >> 1 ;
		int res = 0 ;
		if(L <= m) res = Math.max(res , query(L, R, root<<1, l, m)) ;
		if(R > m) res = Math.max(res , query(L, R, root<<1|1, m+1 , r)) ;
		return res ;
	}
}

class InputReader {
	public BufferedReader reader;
	public StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream), 32768);
		tokenizer = new StringTokenizer("") ;
	}
	
	private void eat(String s){
		tokenizer = new StringTokenizer(s) ;
	}
	
	public String nextLine(){
		try {
			return reader.readLine() ;
		} catch (Exception e) {
			return null ;
		}
	}
	
	public boolean hasNext(){
		while(!tokenizer.hasMoreTokens()){
			String s = nextLine() ;
			if(s == null) return false ;
			eat(s) ;
		}
		return true ;
	}
	
	public String next() {
		hasNext() ;
		return tokenizer.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}

	public BigInteger nextBigInteger() {
		return new BigInteger(next());
	}

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值