kuangbin——线段树专题 H - Tunnel Warfare

来源:互联网 发布:mac 相对于卷宗的格式 编辑:程序博客网 时间:2024/06/05 19:44

H - Tunnel Warfare
Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones. 

Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately! 

Input

The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event. 

There are three different events described in different format shown below: 

D x: The x-th village was destroyed. 

Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself. 

R: The village destroyed last was rebuilt. 

Output

Output the answer to each of the Army commanders’ request in order on a separate line. 

Sample Input

7 9D 3D 6D 5Q 4Q 5RQ 4RQ 4

Sample Output

1024

大体思路比较简单,就是利用线段数求区间
最大和最小值。
这里假设其为              1 2 3 4 5 6 7 
则如果 其中有若干个村子被毁了,如果要求第4个村子
只需求出来   
1->4区间中被毁村子的最大值(2), 

和                 4->7 区间中被毁村子的最小值(5),

根据两者求出村子的连续区间,即  2->5   所以其村子连续个数 为 5-2-1 = 2

即minn - maxx -1

特殊情况:  如果1 2 3 4 5 6 7 求2的连续区间 ,其最大为2,最小也为2

则其连续个数为  0 


思路出来了,这里就借助线段树,来求区间的最大值和最小值。

这里注意,对于没有被摧毁的村子,不加入到线段数节点,而是分别用

0(求最大值时)和n+1(求最小值时)代替,这样能保证,其不影响加入村子的求极值

而且最其在没有村子被摧毁的情况下,也能正确的求出解。

例子:  1 2 3 4 5 6 7

求村子3的连续区间,这里1->3  maxx为0  ;  3->n  minn为4   

所以其连续空间为4-0-1 =3  为正解

可以自己再试其他例子


到这里,线段树就构造好了

求区间最大最小值,直接套线段树模板就好。

下面直接上代码:



#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <algorithm>#define INF 0x3f3f3f3fusing namespace std;typedef long long ll;#define M 50015#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef struct SegTreeNode{    int maxx;    int minn;}segtree;   //线段树结构体,一个用来求最大值,一个用来求最小值segtree arr[M<<2];int n;int history[M<<2];//保存历史,用于Rvoid build(int l,int r,int rt)//建树{    if(l == r){        arr[rt].minn = n+1;        arr[rt].maxx = 0;        return;    }    int m = (l+r)>>1;    build(lson);    build(rson);    arr[rt].maxx = max(arr[rt<<1].maxx,arr[rt<<1|1].maxx);    arr[rt].minn = min(arr[rt<<1].minn,arr[rt<<1|1].minn);}void update_maxx(int p,int sc,int l,int r ,int rt)//更新求最大值的线段树{    if(l == r)    {        arr[rt].maxx = sc;        return ;    }    int m = (l+r)>>1;        if(p<=m)        update_maxx(p,sc,lson);    else        update_maxx(p,sc,rson);    arr[rt].maxx = max(arr[rt<<1].maxx,arr[rt<<1|1].maxx);}void update_minn(int p,int sc,int l,int r ,int rt)//更新求最小值的线段树{    if(l == r)    {        arr[rt].minn = sc;        return ;    }    int m = (l+r)>>1;        if(p<=m)        update_minn(p,sc,lson);    else        update_minn(p,sc,rson);    arr[rt].minn = min(arr[rt<<1].minn,arr[rt<<1|1].minn);}int query_minn(int L,int R,int l,int r ,int rt)   //查找区间最小值{    if(L<=l && r<=R)    {        return arr[rt].minn;    }    int m = (l + r) >>1;    int ret = INF;    if(L<=m)        ret = min(ret,query_minn(L,R,lson));    if(R>m)        ret = min(ret,query_minn(L,R,rson));    return ret;}int query_maxx(int L,int R,int l,int r ,int rt) //查找区间最大值{    if(L<=l && r<=R)    {        return arr[rt].maxx;    }    int m = (l + r) >>1;    int ret = 0;    if(L<=m)        ret = max(ret,query_maxx(L,R,lson));    if(R>m)        ret = max(ret,query_maxx(L,R,rson));    return ret;}int main(int argc, char const *argv[]){int m,a,temp,count;char ch[10];while(scanf("%d %d",&n,&m) == 2){        count = 0;  //历史计算器        memset(history,0,sizeof(history));        memset(arr,0,sizeof(arr));        build(1,n,1);while(m--){scanf("%s",ch);if(ch[0] == 'D')            {                scanf("%d",&a);update_minn(a,a,1,n,1);//更新线段数的值,把a对应的值更新成aupdate_maxx(a,a,1,n,1);history[++count] = a;  //存储到历史记录中}else if(ch[0] == 'Q'){int re,max1,min1;                scanf("%d",&a);max1=query_maxx(1,a,1,n,1);//根据线段树查询min1=query_minn(a,n,1,n,1);                if(max1 == min1)         //考虑特殊情况printf("%d\n",0);else printf("%d\n",min1-max1-1);}else {                temp = history[count--];    update_minn(temp,n+1,1,n,1); //如果恢复,就把对应的值改为0或n+1  update_maxx(temp,0,1,n,1);     }}    }return 0;}



poj 题目链接:http://poj.org/problem?id=2892

  




0 0
原创粉丝点击