HDU 1540 Tunnel Warfare(线段树单点更新+区间合并)

Problem 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 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4

Sample Output

1
0
2
4

线段树区间合并:重建过程可以看出来是湛储存。

对于每个区间(l,r)我们考虑lsum:表示左起最大连续值。

rsum:表示右起最大连续值,maum:区间的最大连续值.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<bitset>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pair<int,int>pil;
const int maxn=50000+10;
int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];
int s[maxn],n,m,top;
void pushup(int rs,int s)
{
    lsum[rs]=lsum[rs<<1];
    rsum[rs]=rsum[rs<<1|1];
    if(lsum[rs<<1]==(s-(s>>1)))  lsum[rs]+=lsum[rs<<1|1];
    if(rsum[rs<<1|1]==(s>>1))  rsum[rs]+=rsum[rs<<1];
    msum[rs]=max(max(msum[rs<<1],msum[rs<<1|1]),rsum[rs<<1]+lsum[rs<<1|1]);
}
void build(int l,int r,int rs)
{
    lsum[rs]=rsum[rs]=msum[rs]=r-l+1;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    build(l,mid,rs<<1);
    build(mid+1,r,rs<<1|1);
    pushup(rs,r-l+1);
}
void update(int x,int c,int l,int r,int rs)
{
    if(l==r)
    {
        lsum[rs]=rsum[rs]=msum[rs]=c;
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid)  update(x,c,l,mid,rs<<1);
    if(x>mid)  update(x,c,mid+1,r,rs<<1|1);
    pushup(rs,r-l+1);
}
int query(int x,int l,int r,int rs)
{
    if(l==r||msum[rs]==0||msum[rs]==r-l+1)
       return msum[rs];
    int mid=(l+r)>>1;
    if(x<=mid)//x点在左区间
    {
        if(x>=mid-rsum[rs<<1]+1)//在靠右连续区间里
            return rsum[rs<<1]+query(mid+1,mid+1,r,rs<<1|1);
        else
            return query(x,l,mid,rs<<1);
    }
    else
    {
       if(x<=mid+lsum[rs<<1|1])
           return lsum[rs<<1|1]+query(mid,l,mid,rs<<1);
       else
           return query(x,mid+1,r,rs<<1|1);
    }
}
int main()
{
    char str[3];
    int x;
    while(~scanf("%d%d",&n,&m))
    {
        build(1,n,1);
        top=0;
        while(m--)
        {
           scanf("%s",str);
           if(str[0]!='R')  scanf("%d",&x);
           if(str[0]=='D')
           {
               update(x,0,1,n,1);
               s[top++]=x;
           }
           if(str[0]=='R')
           {
               x=s[--top];
               update(x,1,1,n,1);
           }
           if(str[0]=='Q')
              printf("%d\n",query(x,1,n,1));
        }
    }
    return 0;
}
时间: 2024-10-29 10:46:16

HDU 1540 Tunnel Warfare(线段树单点更新+区间合并)的相关文章

hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1540 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Gene

hdu 3308 线段树单点更新 区间合并

http://acm.hdu.edu.cn/showproblem.php?pid=3308 学到两点: 1.以区间端点为开始/结束的最长......似乎在Dp也常用这种思想 2.分类的时候,明确标准逐层分类,思维格式: 条件一成立: { 条件二成立: { } else { } } else { 条件二成立: { } else { } } 上面的这种方式很清晰,如果直接想到那种情况iif(条件一 &条件二)就写,很容易出错而且把自己搞乱,或者情况不全,,,我就因为这WA了几次 3.WA了之后 ,

hdu 1540 Tunnel Warfare(线段树)

题目链接:hdu 1540 Tunnel Warfare 题目大意:有连续的N个城镇,三种操作: D x:第x城镇被破坏 Q x:插叙第x城镇所在联通块有多少个城镇没有被破坏 R:修复最后一个被破坏的城镇 解题思路:线段树区间合并,每个城镇看成一个叶子节点,用一个vector记录破坏顺序.对于查询来说,每次只要判断是否在mid?R[lson(u)],mid+L[rson(u)]之间即可,否则即递归查询左右子树. #include <cstdio> #include <cstring>

HDU 1540 Tunnel Warfare 线段树:单点更新,区间合并

Tunnel Warfare                                  Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast

HDU 1540 Tunnel Warfare 线段树区间合并

Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区间,左儿子的最大连续右区间+右儿子的最大连续左区间)决定 所以线段树的节点应该维护当前节点的最大连续左区间,最大连续右区间,和最大连续区间. 注意更新的时候,如果左儿子全满,父亲节点的左连续区间还要加上右儿子的左区间.反之同理. 查询的时候,可以剪枝,如果是叶子,或为空,或满,则不用往下查询. 查询

POJ 2892 Tunnel Warfare(线段树单点更新区间合并)

Tunnel Warfare Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7876   Accepted: 3259 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally sp

HDU 1540 Tunnel Warfare (线段树或set水过)

题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少. 析:首先可以用set水过,set用来记录每个被破坏的村庄,然后查找时,只要查找左右两个端点好. 用线段树的话,就维护三个值分别是左端点连续右端点连续,全连续的最长的区别,然后用线段树维护就好. 代码如下: set过: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #includ

HDU 1540 Tunnel Warfare(线段树 区间合并 最大连续区间)

题意  有n个连在一起的地道  接下来有m个操作  D x 炸掉x号地道  炸掉后x所在的区间就不连续了  Q x 查询输出包括x的最大连续区间长度   R修复最后一个被炸的地道  注意输入R时可能并没有需要修复的地道 线段树的区间合并问题  线段树要维护3个信息 len  对应区间的最大连续长度 ll  对应区间最左端的一段连续长度 lr  对应区间最右端的一段连续长度 那么双亲节点的这些信息和孩子节点有什么关系呢  容易发现 双亲的len 是 左孩子的len 右孩子的len  左孩子的右端长

HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出对应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  对应区间的LCIS长度(lcis)  对应区间以左端点为起点的LCIS长度(lle)  对应区间以右端点为终点的LCIS长度(lri)  然后用val存储数组对应位置的值  当val[mid + 1] > val[mid] 的时候就要进行区间合并操作了 #include <cstdio> #include <algorithm>