1 条题解

  • 0
    @ 2026-5-3 7:38:00

    考虑一些显然不合法的情况,有以下两种:

    • (u,v)(u,v) 边最后亮灯,但是 uuvv 最后均不亮。
    • (u,v)(u,v) 边最后不亮,但是 uuvv 最后均亮灯。

    先判掉这两种情况之后,可以考虑其他四种可能合法的情况:

    • 最后 uu 亮灯,vv 不亮,(u,v)(u,v) 边亮灯,显然可以得出 vv 一定需要在 uu 之后进行最后一次操作,如一种方案是依次进行这些操作:vv 开灯,uu 开灯,vv 关闭,而一开始的 vv 开灯这个操作,可以放到所有操作开头,所以只需要满足 vv 关闭这个操作 在 uu 开灯这个操作后面即可。
    • 最后 uu 亮灯,vv 不亮,(u,v)(u,v) 边不亮,可得 vv 一定在 uu 之前进行最后一次操作,同理,vv 在开头先进行开灯操作,然后需要满足 vv 关闭这个操作在 uu 开灯这个操作前面。

    对于最终 uu 不亮 vv 亮,其实就是相反的情况。

    另外两种情况(u,v,(u,v)u,v,(u,v) 最后均亮灯以及 u,v,(u,v)u,v,(u,v) 最后均不亮),对 uuvv 先后顺序没有限制,如果最后要求均亮灯,则在一开始对 uuvv 进行开灯操作即可。

    那么考虑建一张有向图,xyx\to y 表示 xx 必须在 yy 之前进行操作,跑一遍拓扑排序,如果有环就是不合法的,否则就是合法的。

    如果合法,根据拓扑序的结果进行开灯或者关灯操作即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) x&-x
    int n,q,a1,a2;
    int a[500010],b[500010];
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>st;
    int tree[2000010],bit[500010];
    int posl[500010],posr[500010],ans[500010];
    vector<pair<int,int>>v[500010],ql[500010],qr[500010];
    int ls(int x){
        return x<<1;
    }
    int rs(int x){
        return x<<1|1;
    }
    void update(int now,int x,int l,int r,int num,int typ){
        if(l==r){
            tree[x]=num;
            return;
        }
        int mid=l+r>>1;
        if(now<=mid) update(now,ls(x),l,mid,num,typ);
        else update(now,rs(x),mid+1,r,num,typ);
        if(typ==0) tree[x]=min(tree[ls(x)],tree[rs(x)]);
        else tree[x]=max(tree[ls(x)],tree[rs(x)]);
    }
    int query(int L,int R,int x,int l,int r,int typ){
        if(L<=l&&r<=R) return tree[x];
        int mid=l+r>>1;
        if(L<=mid&&mid<R){
            if(typ==0) return min(query(L,R,ls(x),l,mid,typ),query(L,R,rs(x),mid+1,r,typ));
            else return max(query(L,R,ls(x),l,mid,typ),query(L,R,rs(x),mid+1,r,typ));
        }
        if(L<=mid) return query(L,R,ls(x),l,mid,typ);
        return query(L,R,rs(x),mid+1,r,typ); 
    }
    void addbit(int x,int num){
        while(x<=n){
            bit[x]+=num;
            x+=lowbit(x);
        }
    }
    int querybit(int x){
        int res=0;
        while(x>0){
            res+=bit[x];
            x-=lowbit(x);
        }
        return res;
    }
    signed main(){
        ios::sync_with_stdio(0);
        cin.tie(0),cout.tie(0);
        cin>>n>>q;
        for(int i=1;i<=n;i++){
            cin>>a[i]>>b[i];
        }
        for(int i=1;i<=n*4;i++) tree[i]=2e9;
        st.push({a[1]+b[1],1});
        update(1,1,1,n,1,0);
        posl[1]=0;
        for(int i=2;i<=n;i++){
            while(!st.empty()&&st.top().first<=a[i]){
                update(st.top().second,1,1,n,2e9,0);
                st.pop();
            }
            if(a[i]-b[i]<a[1]){
                posl[i]=0;
                update(i,1,1,n,1,0);
                st.push({a[i]+b[i],i});
            }else{
                int temp=upper_bound(a+1,a+i,a[i]-b[i])-a;
                if(temp==i){
                    posl[i]=i;
                    update(i,1,1,n,i+1,0);
                }else{
                    int temp2=query(temp,i-1,1,1,n,0);
                    posl[i]=temp2-1;
                    posl[i]=min(temp,posl[i]);
                    update(i,1,1,n,posl[i]+1,0);
                    if(posl[i]!=i){
                        st.push({a[i]+b[i],i});
                    }
                }
            }
        }
        for(int i=1;i<=n*4;i++) tree[i]=0;
        while(!st.empty()) st.pop();
        st.push({b[n]-a[n],n});
        update(n,1,1,n,n,1);
        posr[n]=n+1;
        for(int i=n-1;i>0;i--){
            while(!st.empty()&&-st.top().first>=a[i]){
                update(st.top().second,1,1,n,0,1);
                st.pop();
            }
            if(a[i]+b[i]>a[n]){
                posr[i]=n+1;
                update(i,1,1,n,n,1);
                st.push({b[i]-a[i],i});
            }else{
                int temp=lower_bound(a+i+1,a+n+1,a[i]+b[i])-a-1;
                if(temp==i){
                    posr[i]=i;
                    update(i,1,1,n,i-1,1);
                }else{
                    int temp2=query(i+1,temp,1,1,n,1);
                    posr[i]=temp2+1;
                    posr[i]=max(temp,posr[i]);
                    update(i,1,1,n,posr[i]-1,1);
                    if(posr[i]!=i){
                        st.push({b[i]-a[i],i});
                    }
                }
            }
        }
        for(int i=1;i<=n;i++){
            //cout<<i<<" "<<posl[i]<<" "<<posr[i]<<endl;
            if(posl[i]!=0){
                v[posl[i]].push_back({i,1});
            }
            if(posr[i]<=n){
                v[i].push_back({posr[i],1});
            }
            if(posl[i]>0&&posr[i]<=n){
                v[posl[i]].push_back({posr[i],-1});
            }
        }
        for(int i=1;i<=q;i++){
            cin>>a1>>a2;
            ql[a1].push_back({a2,i});
            qr[a2].push_back({a1,i});
        }
        for(int i=1;i<=n;i++){
            //cout<<i<<endl;
            for(auto j:ql[i]){
                ans[j.second]-=querybit(j.first);
            }
            //cout<<"aaa"<<endl;
            for(auto j:v[i]){
                addbit(j.first,j.second);
            }
            //cout<<"bbb"<<endl;
            for(auto j:qr[i]){
                ans[j.second]+=querybit(i);
            }
           // cout<<"ccc"<<endl;
        }
        for(int i=1;i<=q;i++) cout<<ans[i]<<'\n';
    }
    
    • 1

    信息

    ID
    7579
    时间
    1000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者