AT1504

发布时间 2023-04-24 19:39:03作者: untitled0

题意翻译:

\(N\) 个坐标,给定 \(M\) 个区间覆盖,求最后有多少区间被覆盖的次数不是 \(1\)

无脑选手选择先差分区间修改,再线段树维护区间是否存在 \(1\)

代码以及一些注释:

#include<bits/stdc++.h>
#define F first
#define S second
using namespace std;
constexpr int N=3e5+5,M=1e5+5;
int a[N],dif[N],ans[M],n,m;
pair<int,int>q[M];//存储询问
struct node{
    int l,r;bool no1;//区间内是否存在1
    node *ls,*rs;//指针好啊
    node(int l_,int r_):l(l_),r(r_){}
    int mid(){return (l+r)>>1;}
    void pushup(){no1=ls->no1&&rs->no1;}//“是否存在”显然是与的关系
}*rt;
node* build(int l,int r){//建树函数
    node *cur=new node(l,r);
    if(l==r){cur->no1=a[l]!=1;return cur;}
    cur->ls=build(l,cur->mid());
    cur->rs=build(cur->mid()+1,r);
    cur->pushup();
    return cur;
}
bool query(node *cur,int l,int r){//询问函数
    if(cur->l==l&&cur->r==r)return cur->no1;
    bool ans=1;int mid=cur->mid();
    if(l<=mid)ans&=query(cur->ls,l,min(r,mid));
    if(r>mid)ans&=query(cur->rs,max(l,mid+1),r);
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);//输入输出加速
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>q[i].F>>q[i].S;
        dif[q[i].F]++;dif[q[i].S+1]--;//利用差分,O(1)修改
    }
    for(int i=1;i<=n;i++)a[i]=a[i-1]+dif[i];//差分还原原数组
    rt=build(1,n);
    int tot=0;
    for(int i=1;i<=m;i++)
        if(query(rt,q[i].F,q[i].S))
            ans[++tot]=i;
    cout<<tot<<'\n';
    for(int i=1;i<=tot;i++)cout<<ans[i]<<'\n';
    return 0;
}

不对啊,差分完后是静态区间,直接 ST 表就完事了啊(

果然是无脑选手。