题目:https://loj.ac/problem/2585

算答案的时候要二分!

这样的话,就是对于询问位置 x ,二分出一个最小的 mid 使得 [ x-mid , x+mid ] 里包含所有种类的商店。

判断一个区间里包含所有种类商店的方法是对于每种商店,记录每个这种商店的同类型前驱;然后看看 [ x+mid+1 , INF ] 里所有种类商店的前驱最小值是不是 < x+mid 就行了。

  实现方法就是对于每个种类开一个 set 维护该种类商店的所有位置,再对所有种类开一个线段树维护这个区间里的各种商店的前驱最小值;

  新增一个 x 位置的商店,就改一下线段树 x 位置的值,再改一下 x 的同类型后继位置的线段树的值。删除一个商店也类似。

  因为可能同一时刻同种商店在同一个位置,所以用 multiset ;因为同一时刻不同商店可能在同一个位置,导致同一个位置有不同的前驱值,所以线段树每个叶子开 可删堆 或 set 维护该位置所有前驱,取其中的最小值作为线段树该点的值。

对于无解的情况要特判。可以用一个 可删堆 记录所有种类的最靠前的商店位置,只要在加入或删除商店的时候看看它是不是 set 里最靠前元素即可。

这样是 nlog2n 的。自己实现得很不好,TLE。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#define pb push_back
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
int Mn(int a,int b){return a<b?a:b;}
int Mx(int a,int b){return a>b?a:b;}
const int N=3e5+5,M=3*N,M2=N<<1;//M:time M2:pos
int n,k,Q,R,tp[M],tot,ls[M<<1],rs[M<<1];
int p0,ans[N];
struct Sp{int x,t,a,b;}t[N];
struct Node{
  int x,t,id;
  Node(int x=0,int t=0):x(x),t(t) {}
  bool operator< (const Node &b)const
  {return t<b.t;}
}qr[N];
vector<Node> vt[M<<1];
struct Tr{
  int R,ls[M2<<1],rs[M2<<1],mn[M2<<1];
  multiset<int> st[N];
  multiset<int>::iterator it,it2;
  priority_queue<int,vector<int>,greater<int> > q[M2],dq[M2];
  priority_queue<int> q2,dq2;
  void build(int l,int r,int cr)
  {
    mn[cr]=R; if(l==r)return; int mid=l+r>>1;
    ls[cr]=++tot; build(l,mid,ls[cr]);
    rs[cr]=++tot; build(mid+1,r,rs[cr]);
  }
  void init()
  {
    for(int i=1;i<=n;i++) tp[++R]=t[i].x;
    for(int i=1;i<=Q;i++) tp[++R]=qr[i].x;
    sort(tp+1,tp+R+1); R=unique(tp+1,tp+R+1)-tp-1;
    for(int i=1;i<=n;i++) t[i].x=lower_bound(tp+1,tp+R+1,t[i].x)-tp;
    for(int i=1;i<=Q;i++) qr[i].x=lower_bound(tp+1,tp+R+1,qr[i].x)-tp;
    R++; tot=1; build(1,R,1);
    for(int i=1;i<=k;i++)
      st[i].insert(0), st[i].insert(R);
    for(int i=1;i<=k;i++) q2.push(R);
    for(int i=1;i<=k;i++) q[R].push(0);//
  }
  void frs(int u)
  {
    while(dq[u].size()&&dq[u].top()==q[u].top())
      q[u].pop(), dq[u].pop();
  }
  void mdfy(int l,int r,int cr,int p,int k,bool fx)
  {
    if(l==r)
      {
    if(fx)dq[l].push(k); else q[l].push(k);
    frs(l); mn[cr]=q[l].size()?q[l].top():R;
    return;
      }
    int mid=l+r>>1;
    if(p<=mid)mdfy(l,mid,ls[cr],p,k,fx);
    else mdfy(mid+1,r,rs[cr],p,k,fx);
    mn[cr]=Mn(mn[ls[cr]],mn[rs[cr]]);
  }
  int qry(int l,int r,int cr,int L,int R)
  {
    if(l>=L&&r<=R)return mn[cr];
    int mid=l+r>>1, ret=R;
    if(L<=mid)ret=qry(l,mid,ls[cr],L,R);
    if(mid<R)ret=Mn(ret,qry(mid+1,r,rs[cr],L,R));
    return ret;
  }
  void add(Node u)
  {
    int x=u.x, t=u.t;
    it=st[t].lower_bound(x); it2=it; it2--;
    mdfy(1,R,1,*it,*it2,1); mdfy(1,R,1,*it,x,0);
    mdfy(1,R,1,x,*it2,0);
    if((*it2)==0) dq2.push(*it), q2.push(x);
    st[t].insert(x);
  }
  void del(Node u)
  {
    int x=u.x, t=u.t;
    st[t].erase(st[t].lower_bound(x));
    it=st[t].lower_bound(x); it2=it; it2--;
    mdfy(1,R,1,*it,x,1); mdfy(1,R,1,*it,*it2,0);
    mdfy(1,R,1,x,*it2,1);
    if((*it2)==0) dq2.push(x), q2.push(*it);
  }
  int fnd(int u){return lower_bound(tp+1,tp+R,u)-tp;}
  void upd(Node u)
  {
    int x=u.x, id=u.id;
    while(dq2.size()&&dq2.top()==q2.top())
      dq2.pop(), q2.pop();
    if(q2.top()==R){ ans[id]=-1; return;}
    int l=0,r=Mx(tp[x],tp[R-1]-tp[x]), ret;
    while(l<=r)
      {
    int mid=l+r>>1,p1=fnd(tp[x]-mid),p2=fnd(tp[x]+mid+1);
    int d=qry(1,R,1,p2,R);
    if(d>=p1&&d<p2)ret=mid,r=mid-1;
    else l=mid+1;
      }
    ans[id]=ret;
  }
}T;
void build(int l,int r,int cr)
{
  if(l==r)return; int mid=l+r>>1;
  ls[cr]=++tot; build(l,mid,ls[cr]);
  rs[cr]=++tot; build(mid+1,r,rs[cr]);
}
void ins(int l,int r,int cr,int L,int R,Node k)
{
  if(l>=L&&r<=R){vt[cr].pb(k);return;}
  int mid=l+r>>1;
  if(L<=mid)ins(l,mid,ls[cr],L,R,k);
  if(mid<R)ins(mid+1,r,rs[cr],L,R,k);
}
void dfs(int l,int r,int cr)
{
  for(int i=0,lm=vt[cr].size();i<lm;i++)
    T.add(vt[cr][i]);
  if(!ls[cr])
    {
      while(p0+1<=Q&&qr[p0+1].t==l)
    T.upd(qr[++p0]);
    }
  else
    {
      int mid=l+r>>1; dfs(l,mid,ls[cr]); dfs(mid+1,r,rs[cr]);
    }
  for(int i=0,lm=vt[cr].size();i<lm;i++)
    T.del(vt[cr][i]);
}
int main()
{
  n=rdn();k=rdn();Q=rdn();
  for(int i=1;i<=n;i++)
    {
      t[i].x=rdn(); t[i].t=rdn(); t[i].a=rdn(); t[i].b=rdn();
      tp[++R]=t[i].a; tp[++R]=t[i].b;
    }
  for(int i=1;i<=Q;i++)
    {
      qr[i].x=rdn(); qr[i].t=rdn();
      qr[i].id=i; tp[++R]=qr[i].t;
    }
  sort(tp+1,tp+R+1); R=unique(tp+1,tp+R+1)-tp-1;
  for(int i=1;i<=n;i++)
    {
      t[i].a=lower_bound(tp+1,tp+R+1,t[i].a)-tp;
      t[i].b=lower_bound(tp+1,tp+R+1,t[i].b)-tp;
    }
  for(int i=1;i<=Q;i++) qr[i].t=lower_bound(tp+1,tp+R+1,qr[i].t)-tp;
  tot=1; build(1,R,1);  T.init();
  for(int i=1;i<=n;i++)
    ins(1,R,1,t[i].a,t[i].b,Node(t[i].x,t[i].t));
  sort(qr+1,qr+Q+1);
  dfs(1,R,1);
  for(int i=1;i<=Q;i++)printf("%d\n",ans[i]);
  return 0;
}
View Code

相关文章: