题目链接:HDU 1540
题意:
题意是一条线上的点,D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点。
最近在做线段树的专题,碰巧做到了这题,自己没有想出思路,百度出来的题解也没有认真看。。
这次回来又想了一下,查询最长连续点的个数,也就是查询其左右两边最近的破坏点的坐标,然后求差就是所求个数了。
直接将破坏的数储存在数组二分不就出来结果了。写出来发现阳历不对,数组并不有序,不能二分。而有序的插入,或者再排序都太浪费时间。
于是我们神奇的set出现了~用set的有序性以及删除增加节点的O(log(n))效率,加上lowbound,很容易模拟了出来。
寒假要去实现set ,map!
【源代码】
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
const int maxn = 50000+ 10;
int arr[maxn];
set<int>st;
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
int po = 0;
char ch;
int num;
st.clear();
while(m--){
scanf(" %c",&ch);
if(ch == 'D'){
scanf("%d",&num);
arr[po++] = num; //储存删除的节点
st.insert(num);
}
else if(ch =='Q'){
scanf("%d",&num);
set<int>::iterator l = lower_bound(st.begin(),st.end(),num);
int ll;
if(l == st.end()){ //如果没有找到比当前大的节点,返回的迭代器为尾元素的下一个迭代器,也就是.end()
if(l != st.begin()){
--l;
ll = *l;
++l;
printf("%d\n",n-ll);
}
else{
printf("%d\n",n);
}
}
else{
if(*l == num){ //找到相同节点直接输出0;
printf("%d\n",0);
}
else{
if(l != st.begin()){
--l;
ll = *l;
++l;
printf("%d\n",*l-ll-1);
}
else{
printf("%d\n",*l-1);
}
}
}
}
else{
//cout<<arr[po-1]<<endl;
st.erase(arr[--po]); //R,重建对应删除set中的对应元素;
}
}
}
return 0;
}
【线段树】
明天补上~