一:stl大法好;
考虑把有重合部分的区间重载成相等的,然后利用set去重的性质来做;
(如果不是手动实现,还真不知道set去重的时候是有选择性的去重,并不是去掉跟插入的那个相等的值,也有直接可能去掉你插入的值,挥泪,不了解实现方法的stl不要直接用qwq)
另外,这个想法贼nb啊(来自洛谷题解)%大佬
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fastio ios::sync_with_stdio(false);cin.tie(0);
const int maxn=2e5+10;
struct node{
int l,r;
bool operator < (const node &a)const{
return r<a.l;
}
//重载两个区间重合就是相等
};
set<node>st;
int main()
{
fastio
int n;
cin>>n;
while(n--){
char c;
cin>>c;
if(c=='A'){
int l,r;
cin>>l>>r;
node nd=node{l,r};
int ans=0;
set<node>::iterator it=st.find(nd);//要一个一个删掉set中相等的值
while(it!=st.end()){
ans++;
st.erase(it);
it=st.find(nd);
}
st.insert(nd);
cout<<ans<<endl;
}
else{
cout<<st.size()<<endl;
}
}
return 0;
}
二:线段树:
每次先把所有重叠的区间都清掉,然后在插入新的区间,用vector存删掉的区间数
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int n=1e5+10;//线段树的大小
int x[maxn],y[maxn];
int vis[maxn];//标记删除了的区间
int ans=0;//记录区间的个数变化
int tree[maxn<<2],lazy[maxn<<2];
#define imid int mid=(l+r)>>1;
#define rl (rt<<1)
#define rr (rt<<1|1)
vector<int>vc;//存删掉的区间
void down(int rt){//将标记往下推,标记为0时不需要处理
if(lazy[rt]){
tree[rl]=tree[rr]=lazy[rt];
lazy[rl]=lazy[rr]=lazy[rt];
lazy[rt]=0;
}
}
void up(int rt){//处理父节点的值
if(!tree[rl] || !tree[rr]) tree[rt]=tree[rl]+tree[rr];
//至少一边没有值,父节点跟有值的那一边相等
else if(tree[rl]==tree[rr]) tree[rt]=tree[rl];
//左右孩子相等,父节点的值也跟他们相等
else tree[rt]=-1;
//左右孩子不等且不为0,父节点一定是-1
}
void query(int a,int b,int l,int r,int rt){//查询区间中有无染过的颜色
if(a<=l && r<=b && tree[rt]!=-1){//值为-1表示区间中不只一种颜色,所以继续往下查找
if(tree[rt] && !vis[tree[rt]]){//没有被删除并且在区间中,保存下来然后删除
vis[tree[rt]]=1;
vc.push_back(tree[rt]);
}
return;
}
down(rt);
imid
if(a<=mid) query(a,b,l,mid,rl);
if(b>mid) query(a,b,mid+1,r,rr);
up(rt);
}
void update(int a,int b,int k,int l,int r,int rt){
//更新值,顺便更新lazy标记,此时区间中一定没有别的值
if(a<=l && r<=b){
tree[rt]=lazy[rt]=k;
return;
}
down(rt);
imid
if(a<=mid) update(a,b,k,l,mid,rl);
if(b>mid) update(a,b,k,mid+1,r,rr);
up(rt);
}
int main()
{
memset(vis,0,sizeof(vis));
memset(tree,0,sizeof(tree));
memset(lazy,0,sizeof(lazy));
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){//把i当成他们的颜色号
char c;
scanf(" %c",&c);//前面有空格,不会接收奇奇怪怪的符号
if(c=='A'){
ans++;//区间个数
scanf("%d%d",&x[i],&y[i]);
vc.clear();
query(x[i],y[i],1,n,1);//查询区间中的颜色
for(int j=0;j<vc.size();j++) update(x[vc[j]],y[vc[j]],0,1,n,1);//删除别的颜色
update(x[i],y[i],i,1,n,1);//将此区间染色
printf("%d\n",(int)vc.size());//删除的数目
ans-=vc.size();//更新区间个数
}
else printf("%d\n",ans);
}
return 0;
}