题目链接

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]|t\in[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 = ; //所有右端点初始化为指向本身
for (int i = ; i <= n; i++)
{
pre[i] = i;
ans[i] = ;
} //输入并只记录最小的左端点
for (int i = ; 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 - ; i >= ; --i)
{
if (pre[i] >= pre[i + ])pre[i] = pre[i + ];
}
set<int>help;//最开始的时候把所有数都放进去
for (int i = ; i <= n + ; ++i)help.insert(i); for (int ri = ; ri <= n; ri++)//给所有位置选一个数
{
for (int t = pre[ri - ]; t<pre[ri]; ++t)//补充help
{
help.insert(ans[t]);
}
ans[ri] = *help.begin();//set的第一个数就是最小的
help.erase(help.begin());
}
for (int i = ; i <= n; ++i)printf("%d%c", ans[i], i == n ? '\n' : ' ');
} return ;
}

【总结】

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

2018 杭电多校1 - Distinct Values的更多相关文章

  1. hdu6312 2018杭电多校第二场 1004 D Game 博弈

    Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  2. 【2020杭电多校】Distinct Sub-palindromes 找规律

    题目链接:Distinct Sub-palindromes 题意: 给你一个长度n,你需要找出来一些串,这些串由A...Z和a...z构成.我们设长度为n的所有串中所包含回文子串最少的数量为ans.问 ...

  3. 2018 杭电多校3 - M.Walking Plan

    题目链接 Problem Description There are $$$n$$$ intersections in Bytetown, connected with $$$m$$$ one way ...

  4. 2018 杭电多校1 - Chiaki Sequence Revisited

    题目链接 Problem Description Chiaki is interested in an infinite sequence $$$a_1,a_2,a_3,...,$$$ which i ...

  5. 2018 杭电多校2 - Naive Operations

    题目链接 Problem Description In a galaxy far, far away, there are two integer sequence a and b of length ...

  6. 2018杭电多校第二场1003(DFS,欧拉回路)

    #include<bits/stdc++.h>using namespace std;int n,m;int x,y;int num,cnt;int degree[100007],vis[ ...

  7. 2018杭电多校第六场1009(DFS,思维)

    #include<bits/stdc++.h>using namespace std;int a[100010];char s[20];int zhiren[100010];vector& ...

  8. 2018杭电多校第五场1002(暴力DFS【数位】,剪枝)

    //never use translation#include<bits/stdc++.h>using namespace std;int k;char a[20];//储存每个数的数值i ...

  9. 2018杭电多校第三场1003(状态压缩DP)

    #include<bits/stdc++.h>using namespace std;const int mod =1e9+7;int dp[1<<10];int cnt[1& ...

随机推荐

  1. spring作用

    在SSH框假中spring充当了管理容器的角色.我们都知道hibernate用来做持久层,因为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不用书写大量的SQL语句.Struts是用来 ...

  2. 长沙Uber优步司机奖励政策(12月28日到1月3日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. Spring Boot中使用缓存

    Spring Boot中使用缓存 随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一. 原始的使 ...

  4. 使用 adb 命令一次性为多个设备安装 apk

    使用 adb 命令一次性为多个设备安装 apk 原创 2016年07月15日 10:40:53 3154 命令简介 adb install [-lrtsdg] (file) 把包文件推送到设备上并安装 ...

  5. Python 通过sgmllib模块解析HTML

    """ 对html文本的解析方案-示例:在标签开始的时候检查标签中的attrs属性,解析出所有的参数的href属性值 依赖安装:pip install sgmllib3k ...

  6. OSG的组成结构

    OSG的组成结构 核心结构 OSG的功能类采用“命名空间+类名称”的形式来命名.命名空间的命名方式为:第一个单词小写,后继单词的首字母大写,例如osg.osgUtil.osgViewer等:类的名称则 ...

  7. Python列表操作大全(非常全)

    Python列表操作大全(非常全!!!) 对于python列表的理解可以和C语言里面的数组进行比较性的记忆与对照,它们比较相似,对于python里面列表的定义可以直接用方括号里加所包含对象的方法,并且 ...

  8. python常用命令—ipython3环境下获取某个文件夹下的文件列表

    import os os.listdir('文件夹路径')

  9. LeetCode 700——二叉搜索树中的搜索

    1. 题目 2. 解答 如果根节点为空,直接返回 NULL.如果根节点非空,从根节点开始循环查找,直到节点为空. 如果待查找的值大于当前节点值,节点指向右孩子: 如果待查找的值小于当前节点值,节点指向 ...

  10. leetcode个人题解——#24 Swap Nodes in Pairs

    因为不太熟悉链表操作,所以解决方法烦了点,空间时间多有冗余. 代码中l,r分别是每一组的需要交换的左右指针,temp是下一组的头指针,用于交换后链接:res是交换后的l指针,用于本组交换后尾指针在下一 ...