2013編程之美複賽A :无尽的编号 數據結構+貪心

时间限制: 1000ms 内存限制: 256MB

 

描述

在一条公路上,将要依次建造N座建筑。在每个建筑建成之后,都会用一个01串来给它编号。整条公路从起点到终点,所有建筑的编号都严格按照字典序递增的顺序来排列,而每在一个新的地方建起一个建筑时,它的编号会按以下规则确定:

1) 编号要比前一个建筑(起点方向)的字典序大,比后一个建筑(终点方向)的字典序小

3) 编号一定以1结尾

2) 编号要尽可能短,满足该条件时,字典序尽可能小

最开始时,公路的起点和终点上各有一个建筑,编号分别是0和1。接下来依次给出N个坐标 a1, a2, ..., aN,依次表示下一个建筑将要建造的位置,最后要问,当所有建筑建成时,这些建筑的编号总长度是多少,其中又出现了多少个字符1。所有建筑都在公路起点和终点之间,并且没有两个建筑建在同一个位置。

输入

输入文件包含多组测试数据。

第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。

每组数据中第一行为一个整数 N,表示将要建造的建筑数量,第二行是用单个空格隔开的N个互不相同的整数 a1, a2, ..., aN,表示依次将要建造的建筑所在的坐标。

输出

对于每组测试数据,输出一行"Case #X: Y Z",其中X表示测试数据编号,Y表示所有建筑编号总长,Z表示所有编号中字符1的数量。所有建筑包括起点和终点的这两个建筑。所有数据按读入顺序从1开始编号。

数据范围

小数据:T ≤ 100, 0 < N ≤ 100, 0 ≤ ai ≤ 1000

大数据:T ≤ 10, 0 < N ≤ 50000, 0 ≤ ai ≤ 500000

 

 

样例输入
1

5

1 2 3 4 5
样例输出
Case #1: 22 16

 

分析:
  假設我們上一次插入之後當前位置的最近的左邊位置的串的長度為len1,串中1的個數為num1,最近的右邊的串長度為len2,串中1的個數為num2。我們不難發現,當前位置的1的個數最小為 num1+1,長度最小為 max(len1,len2)

  對此,我們可以通過用樹狀數組或者平衡樹、線段樹、SET之類的來維護一下就行了。

一組數據:

數據:

3

5

1 2 3 4 5

5

5 4 3 2 1

3

2 1 3





答案:

Case #1: 22 16

Case #2: 22 6

Case #3: 10 5

  

代碼如下:

 

/*



分析:

    假設我們上一次插入之後當前位置的最近的左邊位置的串的長度為len1,

    串中1的個數為num1,最近的右邊的串長度為len2,串中1的個數為num2。

    我們不難發現,當前位置的1的個數最小為 num1+1,長度最小為 max(len1,len2)



    對此,我們可以通過用樹狀數組或者平衡樹、線段樹、SET之類的來維護一下

    就行了。



*/

#include <set>

#include <map>

#include <cmath>

#include <queue>

#include <stack>

#include <string>

#include <vector>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef unsigned long long ull;



#define lx(x) (x<<1)

#define rx(x) (x<<1|1)

#define debug puts("here")

#define rep(i,n) for(int i=0;i<n;i++)

#define rep1(i,n) for(int i=1;i<=n;i++)

#define REP(i,a,b) for(int i=a;i<=b;i++)

#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

#define pb push_back

#define RD(n) scanf("%d",&n)

#define RD2(x,y) scanf("%d%d",&x,&y)

#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)



/******** program ********************/



struct node{

    int id,val,len;

    node(){}

    node(int _x,int _v,int q):id(_x),val(_v),len(q){}

    friend bool operator < (node a,node b){

        return a.id>b.id;

    }

    void out(){

        cout<<id<<" "<<val<<" "<<len<<endl;

    }

};



set<node> s;



int main(){



#ifndef ONLINE_JUDGE

	freopen("sum.in","r",stdin);

	//freopen("sum.out","w",stdout);

#endif



    int ncase,n;

    RD(ncase);

    rep1(Ncase,ncase){

        printf("Case #%d: ",Ncase);

        int x;

        RD(n);



        set<node>::iterator it;

        s.clear();

        s.insert( node(-1,0,1) ); // 可以為0

        s.insert( node(10000000,0,1) ); // 可以為500000,這兩處比賽過程中我WA了n次 = =。



        ll ans = 0;

        ll r = 0;

        rep1(i,n){

            RD(x);



            it = s.lower_bound( node(x,0,0) );

            node pre = *it;

            * it --;

            node nex = *it;



            int one = pre.val+1;

            ans += one;

            int len = max(nex.len , pre.len)+1;

            r += len;

            s.insert( node(x,one,len) );

        }

        cout<<r+2<<" "<<ans+1<<endl;

    }



	return 0;

}

 

  

 

你可能感兴趣的:(a)