zoukankan      html  css  js  c++  java
  • BZOJ5462 APIO2018新家(线段树+堆)

      一个显然的做法是二分答案后转化为查询区间颜色数,可持久化线段树记录每个位置上一个同色位置,离线后set+树状数组套线段树维护。这样是三个log的。

      注意到我们要知道的其实只是是否所有颜色都在该区间出现,可以改为查询后缀区间的上一个同色位置中最小的。这样我们就只需要set+线段树就可以维护了,同样二分答案是两个log。直接在线段树上二分就变成了一个log。

      给每种颜色在坐标-inf和inf处加点来避免乱七八糟的讨论。离散化一下。对于相同坐标的点,在叶子维护堆即可。调过样例就能1A了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<queue>
    #include<vector>
    using namespace std;
    #define ll long long
    #define N 600010
    #define inf 600000003
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,q,t,L[N<<2],R[N<<2],tree[N<<2],ans[N],u[N];
    struct data
    {
        int x,t,op;int p,i;
        bool operator <(const data&a) const
        {
            return t<a.t||t==a.t&&abs(op)>abs(a.op);
        }
    }a[N<<2];
    priority_queue<int,vector<int>,greater<int> > ins[N<<2],del[N<<2];
    multiset<int> color[N];
    void build(int k,int l,int r)
    {
        L[k]=l,R[k]=r;tree[k]=inf;
        if (l==r) return;
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    int query(int k,int l,int r,int x,int last)
    {
        if (L[k]==R[k]) return max(u[L[k]]-x,x-last);
        int mid=L[k]+R[k]>>1;
        if (r<=mid) return query(k<<1,l,r,x,min(tree[k<<1|1],last));
        else if (l>mid) return query(k<<1|1,l,r,x,last);
        else
        {
            if (u[mid]-x>x-min(last,tree[k<<1|1])) return query(k<<1,l,mid,x,min(last,tree[k<<1|1]));
            else return min(x-min(last,tree[k<<1|1]),query(k<<1|1,mid+1,r,x,last));
        }
    }
    void modify(int k,int p,int x,int op)
    {
        if (L[k]==R[k])
        {
            if (op==1) ins[k].push(x);else del[k].push(x);
            while (!del[k].empty()&&ins[k].top()==del[k].top()) ins[k].pop(),del[k].pop();
            tree[k]=ins[k].empty()?inf:ins[k].top();
            return;
        }
        int mid=L[k]+R[k]>>1;
        if (p<=mid) modify(k<<1,p,x,op);
        else modify(k<<1|1,p,x,op);
        tree[k]=min(tree[k<<1],tree[k<<1|1]);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5462.in","r",stdin);
        freopen("bzoj5462.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),q=read();
        for (int i=1;i<=n;i++)
        {
            int x=read(),y=read(),l=read(),r=read();
            t++;a[t].x=x,a[t].t=l,a[t].op=1,a[t].p=y;
            t++;a[t].x=x,a[t].t=r+1,a[t].op=-1,a[t].p=y;
            u[i]=x;
        }
        for (int i=1;i<=q;i++) t++,a[t].x=read(),a[t].t=read(),a[t].op=0,a[t].p=0,a[t].i=i,u[n+i]=a[t].x;
        sort(u+1,u+n+q+1);int v=unique(u+1,u+n+q+1)-u-1;u[0]=-inf,u[++v]=inf;
        for (int i=1;i<=t;i++) a[i].x=lower_bound(u,u+v+1,a[i].x)-u;
        build(1,0,v);
        sort(a+1,a+t+1);
        //for (int i=1;i<=t;i++) cout<<a[i].x<<' '<<a[i].t<<' '<<a[i].op<<' '<<a[i].p<<' '<<a[i].i<<endl;
        for (int i=1;i<=m;i++)
        {
            color[i].insert(0),color[i].insert(v);
            modify(1,v,-inf,1);
        }
        for (int i=1;i<=t;i++)
        if (a[i].op==0) ans[a[i].i]=query(1,a[i].x,v,u[a[i].x],inf);
        else if (a[i].op==-1)
        {
            multiset<int>::iterator it=color[a[i].p].find(a[i].x);
            it++;int x=*it;
            it--,it--;int y=*it;
            it++;color[a[i].p].erase(it);
            modify(1,x,u[a[i].x],-1),modify(1,a[i].x,u[y],-1),modify(1,x,u[y],1);
        }
        else
        {
            multiset<int>::iterator it=color[a[i].p].lower_bound(a[i].x);
            int x=*it;
            it--;int y=*it;
            color[a[i].p].insert(a[i].x);
            modify(1,x,u[a[i].x],1),modify(1,a[i].x,u[y],1),modify(1,x,u[y],-1);
        }
        for (int i=1;i<=q;i++) printf("%d
    ",ans[i]>inf/3?-1:ans[i]);
        return 0;
    }
  • 相关阅读:
    SQL注入(手工篇)
    sed命令
    交互输入与for语句
    编程原理
    grep与正则表达式
    重定向和管道符
    shell_oneday_历史命令相关
    python_01_初识python
    C# 上传文件
    C# in 参数化处理 (记)
  • 原文地址:https://www.cnblogs.com/Gloid/p/10140787.html
Copyright © 2011-2022 走看看