题意翻译:
\(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 表就完事了啊(
果然是无脑选手。