• [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\n",ans[i]);
    83 }
    View Code
  • 相关阅读:
    asp.net log4net
    SQLServer客户端连接工具(支持2000,20005,2008)
    html中的table导出Excel
    贝叶斯网(2)Netica:从数据中学习CPT
    贝叶斯网(1)尝试用Netica搭建简单的贝叶斯网并使用贝叶斯公式解释各个bar的结果
    IIPP迷你项目(四)"Pong"
    Coursera课程《Machine Learning》学习笔记(week2)
    IIPP迷你项目(二)"Guess the Number!"
    Coursera课程《Machine Learning》学习笔记(week1)
    IIPP迷你项目(三)“Stopwatch: The Game”
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11523449.html
Copyright © 2020-2023  润新知