P2161 [SHOI2009] 会场预约
思路1: A操作中,要知道有多少个区间是重合的,可以用(树状数组+二分)来维护,用树状数组c[i]维护以i为端点的区间, 将[l,r] 进行二分查询从左端点到0~r右端点,然后判断当前区间是否在选定大区间内,如果query(mid)==query(r)说明重合个数相同,将其删去
B操作只需要用一个全局变量ans记录即可
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,x,y,c[N],a[N],ans=0,anss=0;
int lowbit(int x){return x&(-x);
}
void add(int x,int y){for(int i=x;i<=N;i+=lowbit(i)) c[i]+=y;
}
int query(int x){int res=0;for(int i=x;i;i-=lowbit(i)) res+=c[i];return res;
}
int main(){cin>>n;for(int i=1;i<=n;i++){char ch;cin>>ch;if(ch=='A') {cin>>x>>y;anss=0;while(1){int l=0,r=y;while(l<r){int mid=l+r>>1;if(query(mid)<query(y)) l=mid+1;else r=mid;}if(a[l]>=x){add(l,-1);anss++;ans--;}else break;}add(x,1);a[x]=y;ans++;cout<<anss<<endl;}else cout<<ans<<endl;}return 0;
}
/*
6
A 10 15
A 17 19
A 12 17
A 90 99
A 11 12
B
*/
思路2
用平衡树对区间进行维护。
可以注意到的是,对于当前存在的预约,他们一定是升序排列的(有重叠的都被删了)。
那么就可以用按照位置分裂(预约无论按l还是按r都必定是升序的)。
每次插入一个区间的时候,就直接找出互不重叠的前驱和后继,那么需要删除的就是中间的那一段了(因为区间升序),对于每一个A的答案就是中间那段的siz,合并的时候注意一下顺序
对于B询问,答案就是root的siz
#include<bits/stdc++.h>
#define ll long long
#define lc (t[rt].l)
#define rc (t[rt].r)
using namespace std;
const int N=2e5+10;
int lt;
struct node{ int l,r;
};
struct fhq { int l,r,siz,rnd; node v;
}t[N];
int ct,rt;
char ch[10];
void up(int rt){t[rt].siz=t[lc].siz+t[rc].siz+1;
}
void split(int rt,int &l,int &r,int k){if(!k) l=0,r=rt;else if(t[rt].siz==k) l=rt,r=0;else if(k<=t[lc].siz)r=rt,split(lc,l,lc,k),up(rt);else l=rt,split(rc,rc,r,k-t[lc].siz-1),up(rt);
}
void merge(int &rt,int l,int r) {if(!l||!r) rt=l+r;else if(t[l].rnd<t[r].rnd) rt=l,merge(rc,rc,r),up(rt);else rt=r,merge(lc,l,lc),up(rt);
}
int pre(int rt,node a) {if(!rt) return 0;if(t[rt].v.r<a.l) return pre(rc,a)+t[lc].siz+1;else return pre(lc,a);
}
int nxt(int rt,node a) {if(!rt) return 0;if(t[rt].v.l>a.r)return nxt(lc,a);else return nxt(rc,a)+t[lc].siz+1;
}
int new_node(node a){t[++ct].v=a,t[ct].siz=1;t[ct].rnd=rand()<<15|rand(),t[ct].l=t[ct].r=0;return ct;
}
int build(node a) {int l=pre(rt,a),r=nxt(rt,a),x,y,z,k;split(rt,x,y,r); split(x,z,k,l);int ans=t[k].siz,t=new_node(a);merge(t,z,t);merge(rt,t,y); return ans;
}
int main() {node a;srand((unsigned)time(0));scanf("%d",<);while(lt--) {scanf("%s",ch);if(ch[0]=='A') {scanf("%d%d",&a.l,&a.r);printf("%d\n",build(a));}else printf("%d\n",t[rt].siz);}return 0;
}