要求找出每个a[i],找到离他最近而且权值比它大的点,若距离相同,输出权利最大的那个

我的做法有点复杂,时间也要500+ms,因为只要时间花在了map上。

具体思路是模拟一颗树的建立过程,对于权值最大的那个,必须是-1,次大的那个,必须是pos_peo[mx];就是最大人口的节点id、

然后维护一个单调的序列,记录当前有多少个位置加入了树。用个set保证单调性。小到大

把结构体按人口排序大到小,枚举没个城市,这样保证加入后,后面加入的直接找位置最短即可,人口最对的bigger than now的。

二分一个位置,> now.pos的,枚举它左右,选择即可。注意就是当距离相同的时候,还要再判断一次。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
map<int,int>pos_peo;
map<int,int>pos_pos;
struct data {
int pos,peo;
} a[maxn],b[maxn];
int ans[maxn]; struct cmp1 {
bool operator()(int a,int b) {
return a < b; //
}
};
bool cmp2 (data a,data b)
{
return a.peo > b.peo;
}
set<int,cmp1>SS;
void work ()
{
int n;
scanf ("%d",&n);
int mx = -inf;
for (int i=; i<=n; ++i) {
scanf ("%d%d",&a[i].pos,&a[i].peo);
b[i].pos=a[i].pos;
b[i].peo=a[i].peo;
pos_peo[a[i].peo] = i; //id
pos_pos[a[i].pos] = i;
mx = max(mx,a[i].peo);
}
if (n==) {
printf ("-1\n");
return ;
}
ans[pos_peo[mx]] = -;
int sec = -inf;
for (int i=; i<=n; ++i) {
if (sec < a[i].peo && a[i].peo != mx)
sec = a[i].peo;
}
ans[pos_peo[sec]] = pos_peo[mx]; SS.insert(a[pos_peo[mx]].pos);
SS.insert(a[pos_peo[sec]].pos); sort (a+,a++n,cmp2); // peo up to low set<int>::iterator it;
for (int i=; i<=n; ++i) {
int val = a[i].pos;
int ppeo = a[i].peo;
it = SS.lower_bound(val);
int t1 = inf,t2 = inf;
if (it == SS.begin()) { //在开头
ans[pos_peo[a[i].peo]] = pos_pos[*it];
} else if (it == SS.end()) { //在末尾
it --;
ans[pos_peo[a[i].peo]] = pos_pos[*it];
} else {
int tt1 = *it;
t1 = abs(val - (*it));
it--;
int tt2 = *it;
t2 = abs(val - (*it));
if (t1 < t2) {
ans[pos_peo[a[i].peo]] = pos_pos[tt1];
} else if (t1 > t2) {
ans[pos_peo[a[i].peo]] = pos_pos[tt2];
} else { //xiangdeng
int id2 = pos_pos[tt1];
int id1 = pos_pos[tt2];
int cut2 = abs(b[id2].peo - ppeo);
int cut1 = abs(b[id1].peo - ppeo);
if (cut2 > cut1) {
ans[pos_peo[a[i].peo]] = pos_pos[tt1];
} else {
ans[pos_peo[a[i].peo]] = pos_pos[tt2];
}
}
}
SS.insert(a[i].pos);
}
for (int i=; i<=n; ++i) {
printf ("%d ",ans[i]);
}
printf ("\n");
}
int main()
{
#ifdef LOCAL
freopen("data.txt","r",stdin);
#endif
work ();
return ;
}

其实这个可以用单调栈O(n)解决

首先,对于任何一个city,只有两种可能,选择在它左边的第一个城市,或者选择在它右边的第一个城市,当然这些城市都是要合法的。就是要满足人口数 > 当前城市。

所以首先对pos进行排序。这样压栈的时候就能知道相对位置了。用单调栈预处理ri[i]表示右边第一个合法城市。le[i]同理。比较即可。

为什么是第一个合法城市呢?第二个合法城市不行?这是因为距离要最短,要先满足距离。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
struct node {
int pos, val, id;
bool operator < (const node &rhs) const {
return pos < rhs.pos;
}
}a[maxn], ri[maxn], le[maxn];
int stack[maxn], ans[maxn];
void work ()
{
int n;
scanf ("%d", &n);
for (int i = ; i <= n; ++i) {
scanf ("%d%d", &a[i].pos, &a[i].val);
a[i].id = i;
}
sort (a + , a + + n);
int top = ;
for (int i = ; i <= n; ++i) {
while (top >= && a[i].val > a[stack[top]].val) --top;
++top;
stack[top] = i;
if (top != ) {
le[i] = a[stack[top - ]];
} else {
le[i].id = -inf;
}
}
top = ;
for (int i = n; i >= ; --i) {
while (top >= && a[i].val > a[stack[top]].val) --top;
++top;
stack[top] = i;
if (top != ) {
ri[i] = a[stack[top - ]];
} else {
ri[i].id = -inf;
}
}
for (int i = ; i <= n; ++i) {
int toans;
if (le[i].id == -inf) {
toans = ri[i].id == -inf ? - : ri[i].id;
} else if (ri[i].id == -inf) {
toans = le[i].id == -inf ? - : le[i].id;
} else {
int posL = abs(le[i].pos - a[i].pos);
int posR = abs(ri[i].pos - a[i].pos);
if (posL > posR) {
toans = ri[i].id;
} else if (posL == posR) {
if (le[i].val > ri[i].val) {
toans = le[i].id;
} else {
toans = ri[i].id;
}
} else {
toans = le[i].id;
}
}
ans[a[i].id] = toans;
}
for (int i = ; i <= n; ++i) {
printf ("%d ", ans[i]);
}
} int main ()
{
#ifdef local
freopen("data.txt","r",stdin);
#endif
work ();
return ;
}

单调栈

Gym 100971D Laying Cables 二分 || 单调栈的更多相关文章

  1. Code Forces Gym 100971D Laying Cables(单调栈)

    D - Laying Cables Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u ...

  2. Gym 100971D Laying Cables 单调栈

    Description One-dimensional country has n cities, the i-th of which is located at the point xi and h ...

  3. BZOJ 1012--[JSOI2008]最大数maxnumber(二分&单调栈)

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 14142  Solved: 6049[Subm ...

  4. SPOJ MINSUB - Largest Submatrix(二分+单调栈)

    http://www.spoj.com/problems/MINSUB/en/ 题意:给出一个n*m的矩阵M,和一个面积k,要使得M的子矩阵M'的最小元素最大并且面积大于等于k,问子矩阵M'的最小元素 ...

  5. 51Nod 1279:扔盘子(二分||单调栈)

    1279 扔盘子 1.0 秒 131,072.0 KB 5 分 1级题 有一口井,井的高度为N,每隔1个单位它的宽度有变化.现在从井口往下面扔圆盘,如果圆盘的宽度大于井在某个高度的宽度,则圆盘被卡住( ...

  6. D - Laying Cables Gym - 100971D (单调栈)

    题目链接:https://cn.vjudge.net/problem/Gym-100971D 题目大意:给你n个城市的信息,每一个城市的信息包括坐标和人数,然后让你找每一个城市的父亲,作为一个城市的父 ...

  7. Codeforces gym 100971 D. Laying Cables 单调栈

    D. Laying Cables time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  8. Gym 100971D 单调栈

    D - Laying Cables Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u ...

  9. BZOJ1767/Gym207383I CEOI2009 Harbingers 斜率优化、可持久化单调栈、二分

    传送门--BZOJCH 传送门--VJ 注:本题在BZOJ上是权限题,在Gym里面也不能直接看,所以只能在VJ上交了-- 不难考虑到这是一个\(dp\). 设\(dep_x\)表示\(x\)在树上的带 ...

随机推荐

  1. 洛谷【P1142】轰炸

    我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:https://www.luogu.org/problemnew/show/P ...

  2. 微服务理论之三:RPC框架原理

    RPC调用是面向服务架构场景下进行服务间调用的常用组件,一个完整的RPC调用的流程如图1所示: 图1 RPC调用流程 为了方便RPC调用者和服务者的开发,开发者们开发了很多RPC框架.比较有名的RPC ...

  3. Python-实现与metasploit交互并进行ms17_010攻击

    关于ms17_010,可参考http://www.cnblogs.com/sch01ar/p/7672454.html 目标IP:192.168.220.139 本机IP:192.168.220.14 ...

  4. python 爬虫 之BeautifulSoup

    BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后便可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单. ...

  5. shell入门-grep过滤-1

    正则表达式,就是一个字符串.有一定的规律.我们用指定的字符串匹配一个指定的行.指定的字符串就是正则表达式. 正则表达式有这几个工具:grep egrep sed awk 命令:gerep 说明:过滤出 ...

  6. OpenCV创建轨迹条,图片像素的访问

    .OpenCV创建进度条以及图像对比度,亮度调整 1.创建轨迹条createTrackbar() 函数原型C++: intcreateTrackbar(conststring& trackba ...

  7. linux docket

    什么是 Docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于  ...

  8. ssh动态转发小记

    ssh,一般常用来做远程登录管理,也就是连上远程机器,得到一个shell,然后交互式地在上面敲命令-看结果-再敲命令. 偶尔也会用在脚本里,做些自动化批处理上传下载的操作,但本质上也是用shell来执 ...

  9. R:安装、导入各种包。

    library和require都可以载入包,但二者存在区别. #在一个函数中,如果一个包不存在,执行到library将会停止执行,require则会继续执行.require将会根据包的存在与否返回tr ...

  10. sql 删除重复数据保留一条

    --创建测试表 CREATE TABLE TEST ( DEPTNO ), DNAME ), LOC ) ); --插入测试数据 , 'test1', 'test2'); , 'test1', 'te ...