Description
五福街是一条笔直的道路,这条道路可以看成一个数轴,街上每个建筑物的坐标都可以用一个整数来表示。小明是
一位时光旅行者,他知道在这条街上,在过去现在和未来共有 n 个商店出现。第 i 个商店可以使用四个整数 x_i , t_i, a_i,
b_i 描述,它们分别表示:商店的坐标、商店的类型、商店开业的年份、商店关闭的年份。
小明希望通过时光旅行,选择一个合适的时间,住在五福街上的某个地方。他给出了一份他可能选择的列表,上面 包括了 q
个询问,每个询问用二元组(坐标,时间)表示。第 i 对二元组用两个整数 l_i, y_i 描述,分别表示 选择的地点 l_i 和年份 y_i
。 现在,他想计算出在这些时间和地点居住的生活质量。他定义居住的不方便指数为:在居住的年份,离居住点最远 的商店类型到居住点的距离。类型
t 的商店到居住点的距离定义为:在指定的年份,类型 t 的所有营业的商店中 ,到居住点距离最近的一家到居住点的距离。我们说编号为 i
的商店在第 y 年在营业当且仅当 a_i <= y <= b_i 。注意,在某些年份中,可能在五福街上并非所有 k
种类型的商店都有至少一家在营业。在这种情况下,不方便 指数定义为 -1。你的任务是帮助小明求出每对(坐标,时间)二元组居住的不方便指数。
Input
第一行包含三个整数 n , k 和 q,分别表示商店的数量、商店类型的数量和(坐标,时间)二元组的数量。 接下来 n
行,每行包含四个整数 x_i, t_i, a_i, 和 b_i 用于描述一家商店,意义如题面所述 接下来 q 行,每行包含两个整数
l_i, 和 y_i ,表示一组(坐标,时间)查询 (1<= n,q<= 3e5,1<= k <= n) (1<= x_i,a_i,b_i
<= 1e9,1<= t_i <= k,a_i <= b_i) (1<= l_i,y_i <= 1e8)
Output
输出一行,包含q个整数,依次表示对于q组(坐标、时间)询问求出的结果。
Sample Input
4 2 4
3 1 1 10
9 2 2 4
7 2 5 7
4 1 8 10
5 3
5 6
5 9
1 10
Sample Output
4
2
-1
-1
题解
建议前往loj以获得更加阅读体验…
是被tyb所说的线段树分治吸引过来的…然而并不需要好吧…
没有t的限制的话说不定我还是会做的…
单组询问的话很容易想到二分一个答案然后check 这段范围里面是否包含了所有的颜色,数颜色就好了
虽然这样我似乎只会 的…
思考一下,我们其实要求的并不是这段区间里有多少种颜色,而仅仅是想知道是否包含所有颜色
不妨动态维护一下每种商店在第 个位置前一个商店的位置
每个位置的权赋为在这个位置的商店的 的最小值
没有商店就赋为inf
这样的话,对于 的区间,我们事实上只需要知道 这一段的最小权值是否小于L
因为最小权值总是在 之后第一个出现的某种商店的 产生的
我们可以给每个节点开一个 ,维护这个节点所有商店的
这样单组询问就可以 了
为了避免相同时间相同位置出现同样的商店,我们可以预处理一下…使得每种商店在同一时间同一位置只出现了一个。时间其实可以拆分成两个,一个加入这个商店的时间和一个删除这个商店的时间
全局维护商店种类个set,用于找前驱后继
插入 有助体验
没有卡常…跑的极慢…
主要的思路方式还是通过 这一段不可能再出现这种颜色来做到的…
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXN=1000005;
int dcre[4*MAXN],tp;
int n,K,Q;
multiset<int> se1[MAXN];
multiset<int>::iterator it;
struct segtree
{
multiset<int> se2[4*MAXN];
int mn[4*MAXN];
void buildtree(int now,int l,int r)
{
if(l==r)
{
if(l!=tp+1)mn[now]=999999999;
else
{
for(int i=1;i<=K;i++)se2[now].insert(0);
mn[now]=0;
}
return ;
}
int mid=(l+r)/2;
buildtree(now<<1,l,mid);buildtree(now<<1|1,mid+1,r);
mn[now]=min(mn[now<<1],mn[now<<1|1]);
}
void pushin(int now,int l,int r,int p,int lst)
{
if(l==r)
{
se2[now].insert(lst);it=se2[now].begin();
mn[now]=*it;
return ;
}
int mid=(l+r)/2,lc=now<<1,rc=now<<1|1;
if(p<=mid)pushin(lc,l,mid,p,lst);
else pushin(rc,mid+1,r,p,lst);
mn[now]=min(mn[lc],mn[rc]);
}
void popout(int now,int l,int r,int p,int de)
{
if(l==r)
{
it=se2[now].find(de);se2[now].erase(it);
it=se2[now].begin();mn[now]=*it;
if(!se2[now].size())mn[now]=999999999;
return ;
}
int mid=(l+r)/2,lc=now<<1,rc=now<<1|1;
if(p<=mid)popout(lc,l,mid,p,de);
else popout(rc,mid+1,r,p,de);
mn[now]=min(mn[lc],mn[rc]);
}
int qry(int now,int l,int r,int ql,int qr)
{
if(l==ql&&r==qr)return mn[now];
int mid=(l+r)/2,lc=now<<1,rc=now<<1|1;
if(qr<=mid)return qry(lc,l,mid,ql,qr);
else if(mid+1<=ql)return qry(rc,mid+1,r,ql,qr);
else return min(qry(lc,l,mid,ql,mid),qry(rc,mid+1,r,mid+1,qr));
}
}seg;
struct event
{
int op1,op2,pos,t;//操作类型 加入还是删除 位置 时间
event(){}
event(int _op1,int _op2,int _pos,int _t){op1=_op1;op2=_op2;pos=_pos;t=_t;}
}E[4*MAXN];int len;
bool tcmp(event n1,event n2)
{
if(n1.t!=n2.t)return n1.t<n2.t;
return n1.op1>n2.op1;
}
struct shop
{
int op,l,r,pos;
shop(){}
shop(int _op,int _pos,int _l,int _r){op=_op;pos=_pos;l=_l;r=_r;}
}s1[MAXN];
bool cmp(shop n1,shop n2)
{
if(n1.op!=n2.op)return n1.op<n2.op;
if(n1.pos!=n2.pos)return n1.pos<n2.pos;
return n1.l!=n2.l?n1.l<n2.l:n1.r>n2.r;
}
struct ask{int p,t;}w[MAXN];
void md(event tmp)
{
if(tmp.op2==1)//加入
{
int g=tmp.pos;
it=se1[tmp.op1].lower_bound(g);
int u2=*it;--it;
int u1=*it;seg.popout(1,0,tp+1,u2,u1);
seg.pushin(1,0,tp+1,u2,g);seg.pushin(1,0,tp+1,g,u1);
se1[tmp.op1].insert(tmp.pos);
}
else
{
int g=tmp.pos;
it=se1[tmp.op1].lower_bound(g);
--it;int u1=*it;
++it;++it;int u2=*it;
--it;se1[tmp.op1].erase(it);
seg.popout(1,0,tp+1,g,u1);seg.popout(1,0,tp+1,u2,g);
seg.pushin(1,0,tp+1,u2,u1);
}
}
int fd(int p1,int dis)
{
int ret;
if(dis<0)
{
int l=1,r=p1;dis=-dis;
while(l<=r)
{
int mid=(l+r)/2;
if(dcre[p1]-dcre[mid]<=dis)ret=mid,r=mid-1;
else l=mid+1;
}
}
else
{
int l=p1,r=tp;
while(l<=r)
{
int mid=(l+r)/2;
if(dcre[mid]-dcre[p1]<=dis)ret=mid,l=mid+1;
else r=mid-1;
}
}
return ret;
}
int answer[MAXN];
void solve(event tmp)
{
if(seg.qry(1,0,tp+1,tp+1,tp+1)==0){answer[tmp.op2]=-1;return ;}
int nw=tmp.pos;
int l=0,r=1e9,re=-1;
while(l<=r)
{
int mid=(l+r)/2;
int n1=fd(nw,-mid),n2=fd(nw,mid);
if(seg.qry(1,0,tp+1,n2+1,tp+1)>=n1)re=mid,r=mid-1;
else l=mid+1;
}
answer[tmp.op2]=re;
}
int main()
{
n=read();K=read();Q=read();
for(int i=1;i<=n;i++)
{
s1[i].pos=dcre[++tp]=read();s1[i].op=read();
s1[i].l=read();s1[i].r=read()+1;
}
for(int i=1;i<=Q;i++)w[i].p=dcre[++tp]=read(),w[i].t=read();
sort(dcre+1,dcre+1+tp);
tp=unique(dcre+1,dcre+1+tp)-(dcre+1);
for(int i=1;i<=n;i++)s1[i].pos=lower_bound(dcre+1,dcre+tp+1,s1[i].pos)-(dcre);
for(int i=1;i<=Q;i++)w[i].p=lower_bound(dcre+1,dcre+tp+1,w[i].p)-(dcre);
sort(s1+1,s1+1+n,cmp);
int ggg,ln=0;
for(int i=1;i<=n;i=ggg+1)
{
ggg=i;int r=s1[i].r;
while(ggg<n&&s1[ggg+1].op==s1[i].op&&s1[ggg+1].pos==s1[ggg].pos&&s1[ggg+1].l<=r)r=max(s1[++ggg].r,r);
s1[++ln]=shop(s1[ggg].op,s1[ggg].pos,s1[i].l,r);
}
for(int i=1;i<=K;i++)se1[i].insert(0),se1[i].insert(tp+1);
dcre[tp+1]=dcre[tp]+1;
//-1表示询问 其他表示商店类型
for(int i=1;i<=ln;i++)
{
E[++len]=event(s1[i].op,1,s1[i].pos,s1[i].l);
E[++len]=event(s1[i].op,-1,s1[i].pos,s1[i].r);
}
for(int i=1;i<=Q;i++)E[++len]=event(-1,i,w[i].p,w[i].t);
sort(E+1,E+1+len,tcmp);
seg.buildtree(1,0,tp+1);
for(int i=1;i<=len;i++)
{
if(E[i].op1>0)md(E[i]);
else solve(E[i]);
}
for(int i=1;i<=Q;i++)pr2(answer[i]);
return 0;
}