[bzoj5462]新家
Posted pywbktda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj5462]新家相关的知识,希望对你有一定的参考价值。
先离线,将询问按照时间排序,维护商店出现和消失
对于每一个询问,先二分枚举答案,假设是ans,
即要求对于区间[l-ans,l+ans],商店的种类数是k(l是询问的位置)
(当然需要先将所有位置离散一下,l-ans和l+ans找到等价的位置)
那个条件并不是很好处理,但可以转化成另一个条件:
l+ans的每一个商店的前驱(上一个同类型商店)都不在l-ans之前
,只需要快速求前驱和前驱的最小值就可以了,可以套数据结构
具体来说,就是维护一个线段树和一个set,分别表示:
1.商店前驱的线段树(离散,维护区间min);2.每一种类型的set(查找前驱)
(但因为这个前驱需要支持删除,线段树的叶子节点还要开一个set)
这样的复杂度是o(nlog^2n),但可以直接在线段树上二分:
线段树上二分的是l+ans(二分出来的结果再减掉ans就行了),设
答案是k,答案合法当且仅当k+k的后缀最小值<=2l(l是询问位置)
,而后缀最小值可以在递归下来的时候不断维护,因此可行
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define mid (l+r>>1) 5 #define oo 0x3f3f3f3f 6 struct ji{ 7 int x,k,t,p; 8 bool operator < (const ji &a)const{ 9 return (t<a.t)||(t==a.t)&&(p>a.p); 10 } 11 }a[N*3]; 12 map<int,int>mat; 13 multiset<int>s1[N],s2[N]; 14 multiset<int>::iterator it1,it2; 15 int V,VV,n,m,k,q,r,ans[N],f[N*30],ls[N*30],rs[N*30]; 16 void read(){ 17 for(int i=1;i<=n;i++){ 18 m++; 19 scanf("%d%d%d",&a[m].x,&a[m].k,&a[m].t); 20 a[m++].p=1; 21 a[m]=a[m-1]; 22 scanf("%d",&a[m].t); 23 a[m].p=-1; 24 } 25 for(int i=1;i<=q;i++){ 26 m++; 27 scanf("%d%d",&a[m].x,&a[m].t); 28 a[m].k=i; 29 } 30 sort(a+1,a+m+1); 31 } 32 void update(int &k,int l,int r,int x,int y,int z){ 33 if (!k)k=++V; 34 if (l==r){ 35 if (!mat[l])mat[l]=++VV; 36 l=mat[l]; 37 if (y)s2[l].insert(y); 38 if (z)s2[l].erase(s2[l].lower_bound(z)); 39 if (!s2[l].size())f[k]=oo; 40 else f[k]=*s2[l].begin(); 41 return; 42 } 43 if (x<=mid)update(ls[k],l,mid,x,y,z); 44 else update(rs[k],mid+1,r,x,y,z); 45 f[k]=min(f[ls[k]],f[rs[k]]); 46 } 47 int query(int k,int l,int r,int x,int y){ 48 if (l==r) 49 if (l==oo)return -1; 50 else return l-x; 51 if ((mid<x)||(mid+min(y,f[rs[k]])<2*x))return query(rs[k],mid+1,r,x,y); 52 return query(ls[k],l,mid,x,min(y,f[rs[k]])); 53 } 54 void add(int x,int k){ 55 it1=s1[k].upper_bound(x); 56 it2=it1--; 57 update(r,1,oo,x,*it1,0); 58 update(r,1,oo,*it2,x,*it1); 59 s1[k].insert(x); 60 } 61 void del(int x,int k){ 62 s1[k].erase(s1[k].lower_bound(x)); 63 it1=s1[k].upper_bound(x); 64 it2=it1--; 65 update(r,1,oo,x,0,*it1); 66 update(r,1,oo,*it2,*it1,x); 67 } 68 int main(){ 69 scanf("%d%d%d",&n,&k,&q); 70 read(); 71 f[0]=oo; 72 for(int i=1;i<=k;i++){ 73 s1[i].insert(-oo); 74 s1[i].insert(oo); 75 update(r,1,oo,oo,-oo,0); 76 } 77 for(int i=1;i<=m;i++){ 78 if (a[i].p>0)add(a[i].x,a[i].k); 79 if (a[i].p<0)del(a[i].x,a[i].k); 80 if (!a[i].p)ans[a[i].k]=query(r,1,oo,a[i].x,oo); 81 } 82 for(int i=1;i<=q;i++)printf("%d ",ans[i]); 83 }
以上是关于[bzoj5462]新家的主要内容,如果未能解决你的问题,请参考以下文章