博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2018 Multi-University Training Contest 1 - D Distinct Values (STL+双指针)
阅读量:4541 次
发布时间:2019-06-08

本文共 1562 字,大约阅读时间需要 5 分钟。

题意:数量为N的序列,给定M个区间,要求对每个区间Li,Ri,都有al..r (li<jr), aiaj。构造这个序列使其字典序最小。

分析:如果对于每个所给区间都暴力扫一遍,1e5的数据量肯定会TLE。其实有一些区间被其他区间完全覆盖,那么在处理其他区间的过程中,该区间已经被处理过了。用一个指针R记录当前已经处理到的位置,用一个数组ends[i]记录以点i为左端点的区间,最其最右端的位置;不作为某个区间左端点的位置,其右端点就是自己。对于每次处理,指针R只会不断增加,不会回退。

还有一个问题就是:如果维护能够使用的数值。如果遇到两个区间有重叠的部分,那么回溯地去找能够使用的数值肯定是会超时的。可以将目前能够使用的数值保存在一个set中,并用一个L指针记录的是上一个处理过的区间的起始位置,那么结果数组中[L,i-1]内的数值,其实是可以重复使用的,将其重新加入集合中。

官方代码:

#include 
#include
#include
#include
#include
using namespace std;#define LOCALint main() { int T; #ifdef LOCAL freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif scanf("%d", &T); for (int cas = 1; cas <= T; ++cas) { int n, m; scanf("%d%d", &n, &m); vector
ends(n,-1); for (int i = 0; i < n; ++i) ends[i] = i; for (int i = 0; i < m; ++i) { int l, r; scanf("%d%d", &l, &r); ends[l - 1] = max(ends[l - 1], r - 1); //维护每个点需要处理到的最右的位置 } set
unused; for (int i = 1; i <= n; ++i) unused.insert(i); //一开始1-N的值都是可以使用的 vector
ret(n); int l = 0, r = -1; //指针L和指针R for (int i = 0; i < n; ++i){ if (r >= ends[i]) continue; while (l < i) unused.insert(ret[l++]); //将可以使用的数值重新加入集合 while (r < ends[i]){ ret[++r] = *unused.begin(); //将最小值加入结果中 unused.erase(ret[r]); //在集合中删去 } } for (int i = 0; i < n-1; ++i) printf("%d ", ret[i]); printf("%d\n",ret[n-1]); } return 0;}

 

转载于:https://www.cnblogs.com/xiuwenli/p/9356461.html

你可能感兴趣的文章
Thinkphp5笔记二:创建模块
查看>>
centos 安装mysql
查看>>
Redis 禁用FLUSHALL FLUSHDB KEYS 命令
查看>>
Matlab中imread函数使用报错“不应为MATLAB 表达式”分析
查看>>
MFC ADO数据库操作
查看>>
图像质量评价-NQM和WPSNR
查看>>
面试准备——相关知识
查看>>
每日一字:悟
查看>>
CentOS7.6安装稳定版Nginx
查看>>
LeetCode 1002. Find Common Characters (查找常用字符)
查看>>
建立隐藏管理员用户
查看>>
android设置图文提醒功能
查看>>
ajax跨域提交
查看>>
完成登录与注册页面的前端
查看>>
Mac下source tree 下的安装
查看>>
Q学习原理及例子
查看>>
rpmbuild 源码打包clickhouse,附带打好的rpm包下载地址
查看>>
软件体系结构原理、方法与实践总结
查看>>
2017-2018-1 《程序设计与数据结构》第3周学习总结
查看>>
一些基础语法
查看>>