zoukankan      html  css  js  c++  java
  • Codeforces Codeforces Round #484 (Div. 2) D. Shark

    Codeforces Codeforces Round #484 (Div. 2) D. Shark

    题目连接:

    http://codeforces.com/contest/982/problem/D

    Description

    For long time scientists study the behavior of sharks. Sharks, as many other species, alternate short movements in a certain location and long movements between locations.

    Max is a young biologist. For $n$ days he watched a specific shark, and now he knows the distance the shark traveled in each of the days. All the distances are distinct. Max wants to know now how many locations the shark visited. He assumed there is such an integer $k$ that if the shark in some day traveled the distance strictly less than $k$, then it didn't change the location; otherwise, if in one day the shark traveled the distance greater than or equal to $k$; then it was changing a location in that day. Note that it is possible that the shark changed a location for several consecutive days, in each of them the shark traveled the distance at least $k$.

    The shark never returned to the same location after it has moved from it. Thus, in the sequence of $n$ days we can find consecutive nonempty segments when the shark traveled the distance less than $k$ in each of the days: each such segment corresponds to one location. Max wants to choose such $k$ that the lengths of all such segments are equal.

    Find such integer $k$, that the number of locations is as large as possible. If there are several such $k$, print the smallest one.

    Sample Input

    8
    1 2 7 3 4 8 5 6
    

    Sample Output

    6
    25 1 2 3 14 36
    

    题意

    给定一个k,所有严格小于k的为0,大于等于k的为1,由此产生新序列。
    对于新的序列
    1.要保证所有连续为1的长度相等
    2.满足1情况下,尽可能段数更多
    3.满足2的k尽可能小

    Creating a new sequence, for each element replace by 0, if (x<k); otherwise 1.
    If the new sequence is valid, it must fit these condition:
    1.The length of every consecutive nonempty segments which is made of 1 are same.
    2.The number of consecutive segments is maximum possible satisfying the first condition,
    3.K is smallest possible satisfying the first and second conditions.

    题解:

    用优先队列来枚举k,用并查集维护线段,然后判断线段是否改变了答案

    Use priority_queue to enumeratioin k. Use Disjoint set union to maintain segment, then judge the new segment changing the answer or not.

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n;
    int a[100010];
    using pii = pair<int, int>;
    priority_queue<pii, vector<pii>, greater<pii> > q;
    int fa[100010];
    int sz[100010];
    int sumduan;
    int bigduan;
    int maxduan;
    int ans;
    int ansduan;
    
    int find(int k) {
        return fa[k] == k ? k : fa[k] = find(fa[k]);
    }
    
    void unionfa(int q, int w) {
        if (w > q) swap(q, w);
        fa[q] = w = find(w);
        sz[w] += sz[q];
        return;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cout.tie(nullptr);
        cerr.tie(nullptr);
    
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            sz[i] = 1;
            fa[i] = i;
            q.push(make_pair(a[i], i));
        }
        memset(a, 0, sizeof a);
        for (int i = 1; i <= n; i++) {
            int o = q.top().first;
            int x = q.top().second;
            q.pop();
            a[x] = 1;
            if (a[x - 1] && a[x + 1]) {
                unionfa(x, x - 1);
                unionfa(x, x + 1);
                sumduan--;
            } else if (a[x - 1]) {
                unionfa(x, x - 1);
            } else if (a[x + 1]) {
                unionfa(x, x + 1);
            } else {
                sumduan++;
            }
    
            int f = find(x);
            if (sz[f] > maxduan) {
                maxduan = sz[f];
                bigduan = 1;
            } else if (sz[f] == maxduan) {
                bigduan++;
            }
    
            if (bigduan == sumduan) {
                if (sumduan > ansduan) {
                    ansduan = sumduan;
                    ans = o;
                }
            }
        }
        cout << ans+1 << endl;
    }
    
    
  • 相关阅读:
    五一拆装机学习
    msgbox函数和inputbox函数应该注意的几点
    西游记(3)
    刚刚开通csdn
    c# 快捷键
    JavaBean的属性(Simple,Indexed,Bound,Constrained)【收藏】
    SQL查询语句使用【收藏】
    .NET 对实现IPersistStream接口的对象进行保存和读取
    创建控件数组
    常用数据库JDBC连接写法【收藏】
  • 原文地址:https://www.cnblogs.com/EDGsheryl/p/9175893.html
Copyright © 2011-2022 走看看