A sequence S = {s1, s2, ..., sn} is called heapable if there exists a binary tree T with n nodes such that every node is labelled with exactly one element from the sequence S, and for every non-root node si and its parent sj, sj ≤ si and j < i hold. Each element in sequence S can be used to label a node in tree T only once.
Chiaki has a sequence a1, a2, ..., an, she would like to decompose it into a minimum number of heapable subsequences.
Note that a subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.
对于ai可以往右扩展2个<=ai ,那么对于ai选择j<i aj<=ai 且aj最大。
#include <string>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <set>
int Int()
{
char c;
bool neg=false;
while((c=getchar())<'0'||c>'9')neg=c=='-';
int a=c-'0';
while((c=getchar())>='0'&&c<='9')a=a*10+c-'0';
return neg?-a:a;
}
const int N = 100008 ;
std::set<int> num ;
int color[N], score[N] , cnt[N] ;
std::vector<int> res[N] ;
std::set<int>::iterator it ;
int idx ;
void removeLeft(int i , int val)
{
if(it != num.begin())
{
it-- ;
color[val] = color[*it] ;
if(--cnt[*it] <= 0){
num.erase(*it) ;
}
}
else color[val] = ++idx ;
score[i] = color[val] ;
num.insert(val) ;
cnt[val] = 2 ;
}
void solve()
{
int t, n, val ;
t = Int() ;
while(t-- > 0)
{
n = Int() ;
num.clear() ;
idx = 0 ;
for(int i = 1 ; i <= n ; i++)
{
val = Int() ;
if(num.empty()){
color[val] = ++idx ;
score[i] = color[val] ;
num.insert(val) ;
cnt[val] = 2 ;
continue ;
}
it = num.lower_bound(val) ;
if(it != num.end())
{
if(*it == val)
{
score[i] = color[val] ;
cnt[val] += 1 ;
continue ;
}
else removeLeft(i , val) ;
}
else removeLeft(i , val) ;
}
for(int i = 1 ; i <= idx ; i++)
res[i].clear() ;
for(int i = 1 ; i <= n ; i++)
res[score[i]].push_back(i) ;
printf("%d\n", idx) ;
for(int i = 1 ; i <= idx ; i++)
{
printf("%d", res[i].size()) ;
for(int j = 0 ; j < res[i].size() ; j++)
printf(" %d", res[i][j]) ;
printf("\n") ;
}
}
printf("\n") ;
}
int main()
{
solve() ;
return 0;
}
同样的写法JAVA TLE,ZOJ此题对JAVA不友善啊。
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.NavigableSet;
import java.util.StringTokenizer;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
new Task().solve();
}
}
class Task {
InputReader in = new InputReader(System.in);
PrintWriter out = new PrintWriter(System.out);
final int N = 100008;
NavigableSet<Integer> num = new TreeSet<Integer>();
int[] color = new int[N], score = new int[N], cnt = new int[N];
List<Integer>[] res = new List[N];
{
for (int i = 0; i < N; i++)
res[i] = new ArrayList<Integer>();
}
int idx;
void add(int i, int val, int col) {
color[val] = col;
score[i] = color[val];
num.add(val);
cnt[val] = 2;
}
void solve() {
int t, n, val;
t = in.nextInt();
while (t-- > 0) {
n = in.nextInt();
num.clear();
idx = 0;
for (int i = 1; i <= n; i++) {
val = in.nextInt();
if (num.isEmpty()) {
add(i, val, ++idx);
continue;
}
if (num.contains(val)) {
score[i] = color[val];
cnt[val] += 1;
continue;
}
Integer lower = num.lower(val);
if (lower == null) {
add(i, val, ++idx);
continue;
}
color[val] = color[lower];
if (--cnt[lower] <= 0){
num.remove(lower);
}
add(i, val, color[val]);
}
for (int i = 1; i <= idx; i++)
res[i].clear();
for (int i = 1; i <= n; i++)
res[score[i]].add(i);
out.println(idx);
for (int i = 1; i <= idx; i++) {
out.print(res[i].size());
for (int v : res[i])
out.print(" " + v);
out.println();
}
}
out.println();
out.flush();
}
}
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());
}
}