[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 }
View Code

 

以上是关于[bzoj5462]新家的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj3631] [JLOI2014]松鼠的新家

bzoj3631JLOI2014松鼠的新家

bzoj3631: [JLOI2014]松鼠的新家

BZOJ3631: [JLOI2014]松鼠的新家

BZOJ 3631 [JLOI2014]松鼠的新家

BZOJ 3631: [JLOI2014]松鼠的新家