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;
}

【线段树】

明天补上~

posted @ 2016-01-01 23:07  编程菌  阅读(672)  评论(0编辑  收藏  举报