zoukankan      html  css  js  c++  java
  • 2018 杭电多校1

    题目链接

    Problem Description

    Chiaki has an array of n positive integers. You are told some facts about the array: for every two elements $$$a_i$$$ and  $$$a_j$$$ in the subarray $$$a_{l,r} (l ≤ i < j ≤ r )$$$, $$$a_i≠a_j$$$ holds.
    Chiaki would like to find a lexicographically minimal array which meets the facts.

    Input

    There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
    The first line contains two integers n,m (1 ≤ n,m  ≤ 10$$$^5$$$) -- the length of the array and the number of facts. Each of the next m lines contains two integers $$$ l_i$$$ and $$$r_i$$$ (1 ≤ $$$l_i$$$ ≤ $$$r_i$$$  ≤ 10$$$^5$$$)

    It is guaranteed that neither the sum of all n nor the sum for all m exceeds 10$$$^6$$$.

     
    Output

    For each test case, output n integers denoting the lexicographically minimal array. Integers should be separated by a single space, and no extra spaces are allowed at the end of lines.

     
    Sample Input

     3
    2 1
    1 2
    4 2
    1 2
    3 4
    5 2
    1 3
    2 4

     
    Sample Output

    1 2

    1 2 1 2

    1 2 3 1 1

    标程传送门

    【题意】

    给m个区间[$$$l_i, r_i$$$],要构造一个长度为n的串,每个区间内的数不能有相同的,且整个串的字典序最小

    【思路】

    要求字典序最小,自然想到要按从左到右的顺序对串进行填充,因为最左边的区间一定是从1开始填的,而它一旦填充,由于区间重叠,就会对后面的区间造成影响。在填充的过程中有两个问题需要解决:如何寻找下一个区间?如何维护下一个区间可以使用的数字?

    首先可以肯定的是,如果一个区间被更大的区间包含,就再也不需要考虑它了,因为大的区间满足它也一定满足;因此,需要考虑的区间只可能两两重叠,或不重叠,所以它们的左右端点与其他区间都不一样。

    假设现在处理到了位置$$$i$$$,有一个集合M,记录的是当前可用的所有数字,为了更快的生成M,不能每次都把所有数遍历一遍。从M中去掉位置$$$i$$$选择的数后,继续填充下一个位置$$$i+1$$$有两种可能:两点在同一个区间内,这样$$$i+1$$$直接从M中选一个最小的;两点在不同区间,这个时候[$$$l_{i+1},r_{i+1}$$$]可能已经填充了一部分了,也就是两区间的重叠部分[$$$l_{i+1},r_i$$$],M要加入一些数,变为[$$$l_i,l_{i+1}-1$$$]$$$cup$$$ M,再取出最小的数填充到$$$i+1$$$。

     因此,在填数的过程中需要不断获取区间的起点,对每个位置,都需要知道一个它所在的左端点。同一个位置可能会被多个区间覆盖,但由于实际填数的时候从左到右,所以只需要考虑最靠左的左端点。如果用预处理一遍用数组pre[]记录所有位置的这样的左端点,这些值的意义就是在处理位置$$$i$$$时,必须和位置pre[i]~$$$i-1$$$的数都不相同。

    有了预处理以后,当前可用的数字集合M的维护过程就是,$$$M_{(i+1)} =  (M_{(i)}-{ans[i]})cup{ans[t]|tin[pre[i], i-1]}$$$。M上的操作:插入删除,求最小,所以可以用set来实现。

    【代码】

    #include<stdio.h>
    #include<set>
    using std::set;
    using std::pair;
    #define N_max 100005
    typedef  pair<int,int> PII;
    typedef long long LL;
    #define  INF 0x3f3f3f3f
    PII ipt[N_max];
    int ans[N_max];int n, m;
    int pre[N_max];
    int main() {
        int kase;
        scanf("%d", &kase);
        while (kase--)
        {
            scanf("%d %d", &n, &m);
            int del = 0;
    
            //所有右端点初始化为指向本身
            for (int i = 0; i <= n; i++)
            {
                pre[i] = i;
                ans[i] = 1;
            }
    
            //输入并只记录最小的左端点
            for (int i = 0; i<m; ++i)
            {
                scanf("%d %d", &ipt[i].first, &ipt[i].second);
                if (pre[ipt[i].second] > ipt[i].first)
                    pre[ipt[i].second] = ipt[i].first;
            }
            //更远的pre[i+1]会把pre[i]扩大到同样远
            for (int i = n - 1; i >= 1; --i)
            {
                if (pre[i] >= pre[i + 1])pre[i] = pre[i + 1];
            }
            set<int>help;//最开始的时候把所有数都放进去
            for (int i = 1; i <= n + 1; ++i)help.insert(i);
    
            for (int ri = 1; ri <= n; ri++)//给所有位置选一个数
            {
                for (int t = pre[ri - 1]; t<pre[ri]; ++t)//补充help
                {
                    help.insert(ans[t]);
                }
                ans[ri] = *help.begin();//set的第一个数就是最小的
                help.erase(help.begin());
            }
            for (int i = 1; i <= n; ++i)printf("%d%c", ans[i], i == n ? '
    ' : ' ');
        }
    
        return 0;
    }

    【总结】

    看了很久标程,结合自己的理解写出来了。反思了一下之前自己的写法差不多,但是超时的原因,很有可能是在可用集合的维护上不够精简。如果每次直接填好一个区间→更新M→填下一个区间,其实很多数字在真正被使用前就已经被反复插入/删除了很多次,很浪费时间。

  • 相关阅读:
    PHP读取XML数据中CDATA内数值
    微信支付报ip错,怀疑是因为不能正确获取$_Server[addr])ip导致的
    微信支付错误两个问题的解决:curl出错,错误码:60
    tp框架 验证码的应用注意事项
    PHP结合jQuery.autocomplete插件实现输入自动完成提示的功能
    mysql存储小数
    windows服务器剪贴板不能共用的解决办法
    网页设为首页和添加收藏
    网页qq客服代码并自定义图片
    windows apache开启url rewrite
  • 原文地址:https://www.cnblogs.com/tobyw/p/9358312.html
Copyright © 2011-2022 走看看