HDU1540 Tunnel Warfare(线段树+set)
题目链接: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; }
【线段树】
明天补上~