您的位置:首页 > 其它

HDU4521线段树

2016-06-24 20:59 351 查看


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

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

  提起小明序列,他给出的定义是这样的:

  ①首先定义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());
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: