• 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;
    }
    

      

  • 相关阅读:
    MYSQL数据库学习十二 使用MySQL运算符
    MYSQL数据库学习十一 多表数据记录查询
    MYSQL数据库学习十 单表数据记录查询
    MYSQL数据库学习九 数据的操作
    MYSQL数据库学习八 触发器的操作
    MYSQL数据库学习七 视图的操作
    MYSQL数据库学习六 索引的操作
    MYSQL数据库学习五 表的操作和约束
    MySQL数据库学习四 存储引擎和数据类型
    MySQL数据库学习三 数据库对象和基本操作
  • 原文地址:https://www.cnblogs.com/yejinru/p/3032876.html
Copyright © 2020-2023  润新知