NZEC on INVCNT与Guile on Spoj

时间:2014-01-25 14:42:54

标签: scheme guile

我使用NZEC

的以下代码获取INVCNT
; for lists of length > 2 inversions are the same as the number of elements
; against which the first is greater + the inversions of the remaining
(define (inversions l)
        (cond ((< (length l) 2) 0)
              (else (+ (length (filter (lambda (x) (> (car l) x)) (cdr l)))
                       (inversions (cdr l))))))

(use-modules (ice-9 rdelim))

(define (call-n-times proc n)
        (if (= 0 n)
            '()
            (cons (proc) (call-n-times proc (- n 1)))))

(define (solve)
        (write-line (inversions (call-n-times read (read)))))

(call-n-times solve (read))

请提供任何提示?

1 个答案:

答案 0 :(得分:0)

在很长的列表中进行过滤可能会导致最大的重复错误(规格说高达一千万)而不是使用'(长度(过滤器......'使用折叠

(define (inversion L)
 (let loop ((accumulator 0) (L L))
   (if (null? L)
       accumulator
       (loop 
         (+ accumulator
            (fold
              (lambda (init next)
                (if (> (car l) next)
                    (+ init 1)
                    init))
              0
              (cdr L)))
         (cdr L)))))

其次虽然这更容易阅读,将其折叠成自己的功能

(define (inversions-from-car L)
  (fold
     (lambda (init next)
        (if (> (car l) next)
            (+ init 1)
            init))
      0
      (cdr L)))

(define (inversion L)
 (let loop ((accumulator 0) (L L))
   (if (null? L)
       accumulator
       (loop 
         (+ accumulator
             (inversions-from-car L)     
         (cdr L)))))

这对于数据结构来说似乎是一个很好的问题,因为正如所写的那样,它的复杂性很高。

我认为你可以把它降到n(log n)

假设在与左侧节点数配对的值列表上创建一个排序树。 对于这个集合

'(2 3 8 6 1) -> '(1 2 3 6 8) -> 
(*tree (*entry 3 2 2)
       (*tree (*entry 2 1 1)
              (*tree (*entry 1 0 1)
                     ()
                     ())
              ())
        (*tree (*entry 8 1 1)
               (*tree (*entry 6 0 1)
                      ()
                      ())
               ()))      

* tree和* entry只是type-tage *树应该有一个条目,一个左,右 *条目应该有一个值,#left和number)

首先找到带有零累加器的原始列表中的FIRST

'(2 3 8 6 1)

如果enrty的值与FIRST匹配,则将#left添加到累加器

如果值为entry,则在累加器树的左侧分支上超过FIRST递归

如果条目的值小于FIRST,则在#left添加到累加器的情况下递归到右侧分支

如果是空树,则抛出错误

然后你需要更新树。

如果条目的值等于FIRST,则改变条目以将数字减少一个

如果值是条目多于FIRST,则将条目改为#left减一,并递归左分支

如果条目的值小于第一个,则递归到右分支

如果是空树,则抛出错误

您可以将这些规则合并为一个遍历

另外添加以下规则:如果#left为0且number为零,则如果右分支为null,则将此树变为空树,否则变为右分支。

这是一个粗略的(未经测试的版本)

(define (rev-sorted-list->count-list L) ;;sort should be resverse of
                                        ;; final desired order
 (let loop ((value (car L)) (count 1) (L (cdr L)) (acc '()))
   (cond ((null? L) '())
         ((= value (car l))
          (loop value (+ 1 count) (cdr L) acc))
         (else 
          (loop (car l) 1 (cdr L) (cons (cons value count) acc))))))

(define (make-tree count c-L)
 (let* ((middle (ceiling (+ 1 count) 2))
        (left-count (- middle 1))
        (right-count (-count middle))
        (left (if (= 0 left-count)
                  null-tree 
                  (make-tree left-count c-L)))
        (entry+right
          (let loop ((index 1) (L c-L))
            (if (= index middle) 
                L
                (loop (+ 1 index) (cdr L)))))
        (entry 
         (make-entry 
           (caar entry+right)
           left-count
           (cdar entry+right))))
    (build-tree 
       entry
       left
       (if (= 0 right-count)
           null-tree
           (make-tree right-count (cdr entry+right))))))     

;;form left branches from starting points
;;;form right from stopping points
;;never mutating c-L or copies

;;if count = 0 then null tree

(define (build-tree entry left right)
  (list '*tree entry left right) 

(define (entry tree)
 (cadr tree)
(define (left-branch tree)
 (caddr tree))
(define (right-branch tree)
 (cadddr tree))

(define null-tree (list '*tree '()))
(define (null-tree? tree)
 (null? (entry tree)))

(define (make-entry value Nleft count)
 (let ((vec (make-vector 3)))
  (begin (vector-set! vec 0 value)
         (vector-set! vec 1 Nleft)
         (vector-set! vec 2 count)
         vec)))

;;might meessage passing function here

(define (entry-value entry)
 (vector-ref entry 0))

(define (entry-Nleft entry)
 (vector-ref entry 1))

(define (entry-Nleft-set! entry int)
 (vector-set! entry 1 int))

(define (entry-count entry)
 (vector-ref entry 2))

(define (entry-count-set! entry int)
 (vector-set! entry 2 int))

(define (inversions! Test-List Search-Tree)
 (let loop ((acc 0) (L Test-list) (T Search-tree))
   (cond ((null? L) acc)
         ((null-tree? T) (error "null tree " 
                                 "in inner loop of inversion!"))
         ((= (car L) (entry-value (entry T)))
          (entry-count-set! (entry T)
                            (- (entry-count (entry T)) 1))
          (if (and (= 0 (entry-count (entry T)))
                   (= 0 (entry-Nleft (entry T))))
               (set-cdr! T (right-branch T))
               'skip)
          (loop (+ acc (entry-Nleft (entry T)))
                (cdr L)
                Search-tree))
         ((< (car L) (entry-value (entry T)))
          (entry-Nleft-set! (entry T)
                            (- (entry-Nleft (entry T)) 1))
          (loop acc L (left-branch T)))
         ((> (car L) (entry-value (entry T)))
          (loop (+ acc (entry-Nleft (entry T)))
                L
                (right-branch T))))))