• 51 nod 1521 一维战舰 时间复杂度O(n),同 Codeforces 567D. One-Dimensional Battle Ships 有详细注释


    题目:51nod:

    题目Codeforces:

    题目注意到两个战舰不能挨在一起就可以了。

    // 每一段
    struct node{
        int left;  // 段的左端点
        int right;  // 段的右端点
        int length;  // 段长度
        int ship;  // 段最大容纳战舰数
    }arr[200005];

    每一段可容纳战舰数:

    ship*a + (ship - 1) <= length;   -->   ship = (length+1) / (a+1);(舍去小数部分)

    构造出这么一个数据结构就简单了。

    现在还有一个问题:找到说miss的点所在段还需要时间,就算是二分查找也需要O(log(n)),加上遍历的O(n),时间复杂度O(n*log(n))。

             可不可能会超时呢?我认为有可能,所以保险起见,我用了一个数组index[i]表示第i个点所在的段,用空间换时间,比较值。

    一次就AC了,思路就这么多,上代码把:

    #include <bitsstdc++.h>
    using namespace std;
    typedef long long ll;
    
    // 每一段
    struct node{
        int left;  // 段的左端点
        int right;  // 段的右端点
        int length;  // 段长度
        int ship;  // 段最大容纳战舰数
    }arr[200005];
    int len = 0;   // 段的数量
    
    int index[200005]; // 每一个点所处的段
    
    int n,k,a,m;
    int miss;  // 每一次说miss的位置。
    
    int sumShip = 0;  // 现阶段可容纳最多战舰数
    
    // 获取某段可容纳最大战舰数量
    int maxShip(node node1){
        return (node1.length+1)/(a+1);
    }
    
    //初始化
    void init(){
        arr[0].left = 1;arr[0].right = n;
        arr[0].length = arr[0].right - arr[0].left + 1;
        arr[0].ship = maxShip(arr[0]);
        sumShip = arr[0].ship;
        len = 1;
    }
    
    //更新段
    void updataNode(int miss){
        int con = index[miss];  // miss位置所在段
        node* x = &arr[con];    //取出这个段
        int shipNum = x->ship;
    
        arr[len].left = miss+1;
        arr[len].right = x->right;
        arr[len].length = arr[len].right - arr[len].left + 1;
        arr[len].ship = maxShip(arr[len]);
        replace(index+arr[len].left,index+arr[len].right+1 , con ,len);  // 将其中一部分所在段改变
    
        x->right = miss-1;
        x->length = x->right - x->left + 1;
        x->ship = maxShip(*x);
    
        sumShip -= shipNum - arr[len].ship - x->ship;  // 总容纳战舰数减少的数量等于分段后减少的战舰数量
    
        len++;
    }
    
    int main() {
    
        cin >> n >> k >> a >> m;
    
        init();  // 初始化
    
        for(int i = 1;i <= m; ++i){
            cin >> miss;
            updataNode(miss);  // 更新段
            if(sumShip < k){
                cout << i << endl;
                return 0;
            }
        }
        cout << -1 << endl;
        return 0;
    }
    //written by zhangjiuding.

    代码中涉及到的replace是头文件algorithm中的,

    replace(a+3,a+10,p,q);

    表示的是将a[i](i = [3,9])中的p全部换成q。

  • 相关阅读:
    [BZOJ4553][TJOI2016&HEOI2016]序列
    树套树乱讲的代码
    树套树乱讲
    [Luogu4174][NOI2006]最大获益
    [BZOJ3879]SvT
    [BZOJ3611][HEOI2014]大工程
    [BZOJ1501][NOI2005]智慧珠游戏
    [BZOJ1499][NOI2005]瑰丽华尔兹
    [BZOJ3460] Jc的宿舍
    [HDU4812]D Tree
  • 原文地址:https://www.cnblogs.com/zhangjiuding/p/7449954.html
Copyright © 2020-2023  润新知