首先考虑可以用二分答案来解决询问,可以二分一个长度\(len\),若在区间\([x-len,x+len]\)内包含了所有\(k\)种的商店,那么这个\(len\)就是合法的,可以通过二分来求其最小值。

对每个商店的存在时间转化为在\(a\)时刻出现,在\(b+1\)时刻消失,然后和询问一起离线按时间排序,就可以解决时间这一维的限制了。

然后考虑如何快速查询区间内是否包含所有的商店,和支持维护商店的出现消失。

对于这种区间数颜色的问题,可以对每个位置记录与其商店类型相同的上一个位置\(pre\),发现一个位置上可能会有多个商店,那么这里的\(pre\)改为记录这些商店的到其各自商店类型相同的上一个位置的最小值。

\(pre\)是记录该位置商店类型相同的上一个位置,所以对于区间\([l,r]\),如果从\(r+1\)往后的所有位置的\(pre\)的最小值小于\(l\),那么说明至少有一种商店没在该区间出现。但是\(r+1\)往后可能并不会包含所有\(k\)种商店,因此加入哨兵商店来避免讨论,分别在最前面和最后面加入每种商店各一个。

然后就是如何支持维护\(pre\),对于每个位置开一个\(multiset\)维护该位置所有商店的对应其商店类型的前驱,\(multiset\)中的最小值即为该位置的\(pre\),然后用线段树动态开点来维护区间\(pre\)的最小值,这里其实就是在线段树的每个叶子节点开了一个\(multiset\)来维护信息。

对于商店的出现消失维护,对每种商店类型开一个\(multiset\),维护该类型所有商店的出现位置,然后出现和消失只用解决对于该位置同类型的前驱和后继的影响就行,线段树单点修改即可实现。

若用线段树查询最小值来判定二分,复杂度是\(O(n\ log^2\ n)\)的,可以直接在线段树上二分位置,复杂度就是\(O(n\ log\ n)\)的了。

细节挺多,具体实现就看代码吧。

\(code:\)

#include<bits/stdc++.h>
#define maxn 900010
#define all 200000000
#define mid ((l+r)>>1)
using namespace std;
typedef multiset<int>::iterator muli;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,k,q,tot,root,tree_cnt,num;
int mi[maxn*20],ls[maxn*20],rs[maxn*20],ans[maxn];
multiset<int> p[maxn],s[maxn*20];
struct node
{
int pos,tim,id,opt;
}t[maxn];
bool cmp(const node &a,const node &b)
{
if(a.tim==b.tim) return a.opt<b.opt;
return a.tim<b.tim;
}
void modify(int l,int r,int pos,int v,int type,int &cur)
{
if(!cur) cur=++tree_cnt;
if(l==r)
{
if(type) s[cur].insert(v);
else s[cur].erase(s[cur].find(v));
if(!s[cur].empty()) mi[cur]=*s[cur].begin();
else mi[cur]=all;
return;
}
if(pos<=mid) modify(l,mid,pos,v,type,ls[cur]);
else modify(mid+1,r,pos,v,type,rs[cur]);
mi[cur]=min(mi[ls[cur]],mi[rs[cur]]);
}
int query(int pos)
{
if(num<k) return -1;
int l=1,r=all,cur=root,midmi,rmi=all;
while(l<r)
{
midmi=min(rmi,mi[rs[cur]]);
if(pos>mid||midmi<2*pos-mid) cur=rs[cur],l=mid+1;
else rmi=midmi,cur=ls[cur],r=mid;
}
return l-pos;
}
int main()
{
read(n),read(k),read(q),mi[0]=all;
for(int i=1;i<=k;++i)
{
p[i].insert(-all),p[i].insert(all);
modify(1,all,all,-all,1,root);
}
for(int i=1;i<=n;++i)
{
int x,id,a,b;
read(x),read(id),read(a),read(b);
t[++tot]=(node){x,a,id,1};
t[++tot]=(node){x,b+1,id,0};
}
for(int i=1;i<=q;++i)
{
int pos,tim;
read(pos),read(tim);
t[++tot]=(node){pos,tim,i,2};
}
sort(t+1,t+tot+1,cmp);
for(int i=1;i<=tot;++i)
{
int opt=t[i].opt,id=t[i].id,pos=t[i].pos;
muli a,b;
if(opt==0)
{
a=b=p[id].lower_bound(pos),a--,b++;
modify(1,all,*b,pos,0,root);
modify(1,all,*b,*a,1,root);
modify(1,all,pos,*a,0,root);
if(p[id].size()==3) num--;
p[id].erase(p[id].find(pos));
}
if(opt==1)
{
a=b=p[id].lower_bound(pos),a--;
modify(1,all,*b,pos,1,root);
modify(1,all,*b,*a,0,root);
modify(1,all,pos,*a,1,root);
if(p[id].size()==2) num++;
p[id].insert(pos);
}
if(opt==2) ans[id]=query(pos);
}
for(int i=1;i<=q;++i) printf("%d\n",ans[i]);
return 0;
}

题解 洛谷 P4632 【[APIO2018] New Home 新家】的更多相关文章

  1. 洛谷P4632 [APIO2018] New Home 新家(动态开节点线段树 二分答案 扫描线 set)

    题意 题目链接 Sol 这题没有想象中的那么难,但也绝对不简单. 首先把所有的询问离线,按照出现的顺序.维护时间轴来处理每个询问 对于每个询问\((x_i, y_i)\),可以二分答案\(mid\). ...

  2. 洛谷 P3258 [JLOI2014]松鼠的新家 题解

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

  3. 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)

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

  4. 洛谷P3258 [JLOI2014]松鼠的新家(树上差分+树剖)

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

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

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

  6. 洛谷P3258 [JLOI2014]松鼠的新家

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

  7. 洛谷——P3258 [JLOI2014]松鼠的新家

    https://www.luogu.org/problem/show?pid=3258 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到 ...

  8. 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...

  9. 题解——洛谷P4095 [HEOI2013]Eden 的新背包问题(背包)

    思路很妙的背包 用了一些前缀和的思想 去掉了一个物品,我们可以从前i-1个和后i+1个推出答案 奇妙的思路 #include <cstdio> #include <algorithm ...

随机推荐

  1. Git执行"git rebase -i HEAD~xxx"报错:git rebase fatal: Needed a single revision invalid upstream –i

    一.问题"git rebase -i HEAD~xxx"是修改git 历史记录的一个很有用的命令. 但是有时在执行该命令时会出现以下错误:$ git rebase –i HEAD~ ...

  2. spring框架中JDK和CGLIB动态代理区别

    转载:https://blog.csdn.net/yhl_jxy/article/details/80635012 前言JDK动态代理实现原理(jdk8):https://blog.csdn.net/ ...

  3. ImageLoader在Listview中的使用

    图片加载框架之ImageLoader 1_特点 1)多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等 2)支持随意的配置ImageLoader,例如线程池 ...

  4. python3 闭包函数 装饰器

    闭包函数 1.闭:定义在函数内部的函数 2.包:内部函数引用了外部函数作用域的名字 在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引 ...

  5. Spring IoC bean 的创建(上)

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...

  6. 【neo4j】文件管理路径、数据备份、创建新数据库、导入数据等操作记录

    neo4j一般的配置路径如下 一.备份数据 使用neo4j-admin命令. 首先,先找到数据的存储路径,然后关闭数据库. 关闭数据库的语句如下: #切换到/bin目录下 ./neo4j stop 然 ...

  7. Kubernetes 中 搭建 EFK 日志搜索中心

    简介 Elastic 官方已经发布了Elasticsearch Operator ,简化了 elasticsearch 以及 kibana的部署与升级,结合 fluentd-kubernetes-da ...

  8. 洛谷P1220关路灯【区间dp】

    题目描述 某一村庄在一条路线上安装了 \(n\) 盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯 ...

  9. 【错误】fatal: destination path already exists and is not an empty directory. 错误及解决办法

    今天在使用Git for Windows clone代码时,遇到了题目所示的错误,简单来说就是目标路径‘.’已经存在并且不是一个空目录. 可是在我在文件夹下并没有看到任何文件,显示“该文件夹为空”,然 ...

  10. 问题 C: 最短路径

    问题 C: 最短路径 在洛谷上刷最短路的题然后被老师拉回去做算法笔记上面的题... 拿到这道题,先确定所有路径唯一,然后是无向边,那么对于边权处理,直接赋值为2的k次方就可以了,然后直接跑最短路. 这 ...