题解:AT_arc196_d [ARC196D] Roadway

· · 题解

题,为啥这么久没人写题解来着。结论题的核心思路:必要条件逼近,充分性证明口胡。 下面阐明想到本题结论的动态过程。

最终只需要判断 ①②,双指针,判断 容易,判断 要求维护区间集合支持插入删除查询当前是否满足“分层”条件,直接维护不满足条件的 (l_i,r_i)(l_j,r_j) 对数,插入删除即二维数点,树套树完成。

但是官解指出:

We need to perform insertions and removals of intervals to a set and test whether the current set is laminar; this can be done with Zobrist hashing. To compute the XOR of an interval, we may use a BIT. The total complexity is O((N+M)\log N +Q)

不理解随机异或哈希咋做的,会的在下面叫一声。

:::success[树套树代码]

#include <cstdio>
#include <random>
#include <vector>

using namespace std;

const int N=414514;int n;

mt19937 rnd;

class DS{
    struct node{
        int v,s,ls,rs;unsigned pr;
        #define v(x) t[x].v
        #define s(x) t[x].s
        #define ls(x) t[x].ls
        #define rs(x) t[x].rs
        #define pr(x) t[x].pr
    }t[N*20];int tot;
    void upd(int x){s(x)=s(ls(x))+s(rs(x))+1;}
    void div(int u,int &x,int &y,int k){
        if(!u) return x=y=0,void();
        if(v(u)<=k) x=u,div(rs(u),rs(u),y,k);
        else y=u,div(ls(u),x,ls(u),k);
        upd(u);
    }
    int mrg(int x,int y){
        if(!x||!y) return x|y;
        if(pr(x)<pr(y)){
            rs(x)=mrg(rs(x),y);
            upd(x);return x;
        }else{
            ls(y)=mrg(x,ls(y));
            upd(y);return y;
        }
    }
    int nnd(int k){return t[++tot]=(node){k,1,0,0,rnd()},tot;}
    void ist(int& rt,int k){
        int x,y;div(rt,x,y,k);
        rt=mrg(mrg(x,nnd(k)),y);
    }
    void dlt(int& rt,int k){
        int x,y,z;div(rt,x,z,k);div(x,x,y,k-1);
        rt=mrg(mrg(x,mrg(ls(y),rs(y))),z);
    }
    int qry(int& rt,int l,int r){
        int x,y,z;div(rt,x,z,r);div(x,x,y,l-1);
        int e=s(y);rt=mrg(mrg(x,y),z);
        return e;
    }
    #undef ls
    #undef rs
    int o[N<<2];
    #define ls(x) (x<<1)
    #define rs(x) (x<<1|1)
    void upd(int u,int ln,int rn,int p,int q,bool i){
        i?ist(o[u],q):dlt(o[u],q);
        if(ln==rn) return ;
        int mid=ln+rn>>1;
        if(p<=mid) upd(ls(u),ln,mid,p,q,i);
        else upd(rs(u),mid+1,rn,p,q,i);
    }
    int qry(int u,int ln,int rn,int l,int r,int p,int q){
        if(l<=ln&&rn<=r) return qry(o[u],p,q);
        int mid=ln+rn>>1,e=0;
        if(l<=mid) e+=qry(ls(u),ln,mid,l,r,p,q);
        if(r>mid) e+=qry(rs(u),mid+1,rn,l,r,p,q);
        return e;
    }
    public:int O;
    void del(int l,int r){
        upd(1,1,n,l,r,0);
        O-=qry(1,1,n,l,r-1,r,n)+qry(1,1,n,1,l,l+1,r);
    }
    void ins(int l,int r){
        O+=qry(1,1,n,l,r-1,r,n)+qry(1,1,n,1,l,l+1,r);
        upd(1,1,n,l,r,1);
    }
}F[2];

bool f[N];int l[N],r[N],sr[N],tr[N],sl[N],tl[N],cic;

void del(int i){
    cic-=(f[i]&&!--sr[l[i]]&&tl[l[i]])
        +(f[i]&&!--tr[r[i]]&&sl[r[i]])
        +(!f[i]&&!--tl[l[i]]&&sr[l[i]])
        +(!f[i]&&!--sl[r[i]]&&tr[r[i]]);
    F[f[i]].del(l[i],r[i]);
}

void ins(int i){
    cic+=(f[i]&&!(sr[l[i]]++)&&tl[l[i]])
        +(f[i]&&!(tr[r[i]]++)&&sl[r[i]])
        +(!f[i]&&!(tl[l[i]]++)&&sr[l[i]])
        +(!f[i]&&!(sl[r[i]]++)&&tr[r[i]]);
    F[f[i]].ins(l[i],r[i]);
}

bool ans[N];

struct qry{int e,id;};vector<qry> Q[N];

int main()
{
    int m,q;scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=m;++i){
        scanf("%d%d",l+i,r+i);
        if(!(f[i]=l[i]<r[i])) swap(l[i],r[i]);
    }
    for(int i=1,e,o;i<=q;++i) scanf("%d%d",&e,&o),Q[o].push_back({e,i});
    ins(1);for(int R=1,L=1;;ins(++R)){
        while(cic||F[0].O||F[1].O) del(L++);
        for(auto[e,id]:Q[R]) ans[id]=e>=L;
        if(R==m) break;
    }
    for(int i=1;i<=q;++i) puts(ans[i]?"Yes":"No");
}
/*
114514 5 1
1 4
2 5
3 5
1 2
2 4

3 5
*/

:::