题面

题意

在一条路上有n家商店,每个商店有一个类型,在某段时间内在某个位置上存在,每次询问给出一个时间和一个地点,求该时间从该地点出发最少走多少路才可以到达任意一种类型的商店。

做法

首先可以离线处理,根据时间进行排序,那么没家商店就都可以看作是在某个时间加入,再从某个时间删除,并询问某个点到所有类型点的最小距离的最大值。
这个可以进行二分,这样问题就转化为了,询问此时某一段区间内是否存在所有类型的商店。
对于这个问题,我们可以对于每一个商店记录它左边的第一个同类型的商店的位置pre,那么如果商店iii的preprepre为jjj,就说明区间[i+1,j−1][i+1,j-1][i+1,j−1]中不存在与它同类型的商店,据此,如果所有大于rrr的商店的preprepre均大于等于lll,则说明区间[l,r][l,r][l,r]中包含所有类型的商店(用线段树维护即可),除非某种类型的商店不存在于lll及其右边,对于这种情况只要记录一下每种类型的商店最右边的位置即可。
这题最麻烦的地方在于一个位置可以有多个商店(类型可以相同),因此处理时,可以用multiset记录每种类型的商店的所有商店位置(维护每个商店的pre),然后对于每个位置用一个支持删除的优先队列来维护该位置上所有商店的pre的最小值,再用一个线段树来维护这些优先队列的top即可。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define N 300100
using namespace std;int n,m,Q,bb,cc,tb,tc,ss,tt,ans[N],b[N],cnt[N],cl;
void chg(int now,int l,int r,int u,int v);
struct Shop
{int cz,pos,type,ti;bool operator < (const Shop &u) const{if(ti!=u.ti) return ti<u.ti;return cz<u.cz;}
}shop[N*3];
struct Pq
{int tp,id;priority_queue<int,vector<int>,greater<int> >a,b;void cle(){for(;!b.empty() && a.top()==b.top();a.pop(),b.pop());}int top(){cle();return a.top();}void cg(){if(tp!=top()) tp=top(),chg(1,1,bb,id,tp);}void push(int u){a.push(u);if(id) cg();}void del(int u){b.push(u);if(id) cg();}
}pq[N],ri;
struct Node
{int ls,rs,mn;
}node[N<<1];
map<int,int>mb;
multiset<int>se[N];
multiset<int>::iterator it,i2;inline void add(int u,int v)
{if(!cnt[v]) cl--;cnt[v]++;se[v].insert(u);i2=it=se[v].lower_bound(u);it++,i2--;pq[u].push(*i2);if(it!=se[v].end()) pq[*it].del(*i2),pq[*it].push(u);else ri.del(*i2),ri.push(u);
}inline void del(int u,int v)
{cnt[v]--;if(!cnt[v]) cl++;i2=it=se[v].lower_bound(u);it++,i2--;pq[u].del(*i2);if(it!=se[v].end()) pq[*it].del(u),pq[*it].push(*i2);else ri.del(u),ri.push(*i2);se[v].erase(--it);
}inline void up(int now){int L=node[now].ls,R=node[now].rs;node[now].mn=min(node[L].mn,node[R].mn);}
void build(int now,int l,int r)
{if(l==r){node[now].mn=INF;return;}int mid=((l+r)>>1);node[now].ls=++tt;build(tt,l,mid);node[now].rs=++tt;build(tt,mid+1,r);up(now);
}void chg(int now,int l,int r,int u,int v)
{if(l==r){node[now].mn=v;return;}int mid=((l+r)>>1);if(u<=mid) chg(node[now].ls,l,mid,u,v);else chg(node[now].rs,mid+1,r,u,v);up(now);
}int ask(int now,int l,int r,int u,int v)
{if(u<=l&&r<=v) return node[now].mn;int mid=((l+r)>>1);if(v<=mid) return ask(node[now].ls,l,mid,u,v);if(u>mid) return ask(node[now].rs,mid+1,r,u,v);return min(ask(node[now].ls,l,mid,u,v),ask(node[now].rs,mid+1,r,u,v));
}inline bool judge(int u,int v)
{u=lower_bound(b+1,b+bb+1,u)-b;v=upper_bound(b+1,b+bb+1,v)-b-1;if(v<u) return 0;if(v<bb && ask(1,1,bb,v+1,bb)<u) return 0;if(ri.top()<u) return 0;return 1;
}inline int calc(int u)
{if(cl) return -1;int l,r,mid;for(l=0,r=1e8;l<r;){mid=((l+r)>>1);if(judge(u-mid,u+mid)) r=mid;else l=mid+1;}return l;
}int main()
{int i,j,p,q,o,z;cin>>n>>m>>Q;cl=m;for(i=1;i<=m;i++) se[i].insert(0),ri.push(0);for(i=1;i<=n;i++){scanf("%d%d%d%d",&z,&o,&p,&q);b[++tb]=z;shop[++ss].cz=1;shop[ss].pos=z;shop[ss].type=o;shop[ss].ti=p;shop[++ss].cz=3;shop[ss].pos=z;shop[ss].type=o;shop[ss].ti=q;}for(i=1;i<=Q;i++){scanf("%d%d",&p,&q);shop[++ss].cz=2;shop[ss].pos=p;shop[ss].ti=q;shop[ss].type=i;}sort(b+1,b+tb+1);for(i=1;i<=tb;i++){if(i==1 || b[i]!=b[i-1]){b[++bb]=b[i];mb[b[i]]=bb;}}for(i=1;i<=ss;i++) if(shop[i].cz!=2) shop[i].pos=mb[shop[i].pos];for(i=1;i<=bb;i++) pq[i].id=i,pq[i].push(INF);build(tt=1,1,bb);sort(shop+1,shop+ss+1);for(i=1;i<=ss;i=j){z=shop[j=i].ti;for(;j<=ss&&shop[j].ti==z&&shop[j].cz==1;j++)add(shop[j].pos,shop[j].type);for(;j<=ss&&shop[j].ti==z&&shop[j].cz==2;j++)ans[shop[j].type]=calc(shop[j].pos);for(;j<=ss&&shop[j].ti==z&&shop[j].cz==3;j++)del(shop[j].pos,shop[j].type);}for(i=1;i<=Q;i++) printf("%d\n",ans[i]);
}

APIO2018 新家相关推荐

  1. [APIO2018] New Home 新家(线段树,二分答案,离散化)

    [APIO2018] New Home 新家 Solution 对于时间轴我们直接离散化+扫描线,维护每一个商店的加入和删除. 对于询问(x,t)(x,t)(x,t),不好直接回答,这里的关键一步是: ...

  2. Loj #2585. 「APIO2018」新家

    Loj #2585. 「APIO2018」新家 题目描述 五福街是一条笔直的道路,这条道路可以看成一个数轴,街上每个建筑物的坐标都可以用一个整数来表示.小明是一位时光旅行者,他知道在这条街上,在过去现 ...

  3. 博客搬家了--这次搬进自己家的了,不过博客园的会定时更新!新家地址: http://blog.woshimaijia.com/...

    博客搬家了--这次搬进自己家的了,不过博客园的会定时更新! 新家地址: http://blog.woshimaijia.com/ 博客园的博客很稳定,也是我很喜欢的地方 这里的文章我也会陆续更新的.. ...

  4. 神策数据搬新家,召唤有才新伙伴!

    随着业务的飞速发展,神策数据小团队不断壮大,为了方便公司团队内部高效工作,服务客户,响应需求,勾肩搭背,约饭开黑--领导决定给大家换一个宽敞的新地盘,大手笔哦!我们搬新家啦! 请记住神策数据大家庭的新 ...

  5. 【NOIP2013模拟】小喵喵的新家

    Description 小喵喵和小聪聪从小就是好朋友 ,他们经常在一起玩耍 .如今小喵已经厌倦了自己居住的环境,想请小聪聪为她建一个新家. 小喵喵天生多才多艺,对多种乐器颇有研究.对于生活中常见的图形 ...

  6. [Luogu 3258] JLOI2014 松鼠的新家

    [Luogu 3258] JLOI2014 松鼠的新家 LCA + 树上差分. 我呢,因为是树剖求的 LCA,预处理了 DFN(DFS 序),于是简化成了序列差分. qwq不讲了不讲了,贴代码. #i ...

  7. P3258 [JLOI2014]松鼠的新家(树上点查分)

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上. ...

  8. P3258 [JLOI2014]松鼠的新家

    文章目录 题意: 题解: 树上差分 代码: 树链剖分 代码: P3258 [JLOI2014]松鼠的新家 题意: n个点,n-1条边,给出每个点的拜访顺序,问每个点经过几次(最后一次移动不算拜访) 题 ...

  9. 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

最新文章

  1. SQLSERVER存储过程基本语法使用
  2. python文件IO操作
  3. Java 程序死锁问题原理及解决方案
  4. .net面试题大全,绝大部分面试题(有答案)
  5. DevExpress的TreeList实现自定义节点NodeCell的背景颜色和前景色
  6. Android微信界面的设计
  7. 电机的入门之路系列2--电机驱动芯片2003的用法
  8. 内存溢出和内存泄漏的区别,产生原因以及解决方案
  9. 不使用第三个变量的情况下,实现两个变量间的互换。
  10. Yolo训练自己的数据集,将json格式转换成txt文件格式
  11. 《计算机网络 自顶向下方法》答案(第七章)
  12. sci论文 计算机,计算机类SCI论文
  13. lsa五类_LSA 的五种类型
  14. Dual Attention机制
  15. 服务器虚拟主机,非根目录jsp文件的引包报错
  16. Unity 手游面数控制
  17. android第三方菜单设计,Android菜单设计指南(上)
  18. 报错 - 使用marked报错 marked__WEBPACK_IMPORTED_MODULE_4___default(...) is not a function
  19. 以后我给你们上课的机会可能越来越少了
  20. linux 服务进程管理,进程管理和系统服务-Linux学习笔记

热门文章

  1. 附录3:实验结果与简单分析
  2. 使用threejs和canvas创建中文文字精灵
  3. ElasticSearch 6.3版本(ES)查询人名关键字不拆词查询
  4. vue项目中videoPlayer 的 src 视频地址参数动态修改---方法
  5. [转]我在赶集网的两个月 7.4(完结)
  6. 中国地质调查局:汶川地震原因已有初步结论
  7. Flutter滑动体验对齐原生-滑动曲线篇
  8. javascript运动框架(三)
  9. 推荐一种英语听力筑基训练方法
  10. 复旦大学邱锡鹏:若优化顺利,MOSS三月底开源;库克或被踢出苹果董事会;华为云联合CSDN发布智能化编程助手Snap|极客头条...