Hdu 1540 && Poj 2892 Tunnel Warfare

Tunnel Warfare

TimeLimit: 4000/2000 MS(Java/Others)    MemoryLimit: 65536/32768 K (Java/Others)
Total Submission(s):2480    AcceptedSubmission(s): 923


Problem Description
During the War of Resistance Against Japan, tunnel warfare wascarried 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 connectedwith two neighboring ones.

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

Input
The first line of the input contains two positive integers nand 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 formatshown below:

D x: The x-th village was destroyed.

Q x: The Army commands requested the number of villages that x-thvillage was directly or indirectly connected with includingitself.

R: The village destroyed last was rebuilt.
 

Output
Output the answer to each of the Army commanders’ request inorder 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
 

Source
POJ Monthly

线段树的题目,第一次做这个题的时候怎么想都没想出来这个题怎么用线段树来解,后来在网上看了N多人的解题报告和代码,才明白这个题的解法,不过后来有事耽搁了,没写这个题的代码,今天再来写这个题的代码,按照记忆中的思路来写的,结果一把代码写出来就过了样例,然后提交就AC了,小小的激动下......0.0

每一个结点保存3个信息:
1:从区域的左端开始连续的未被摧毁的最大村庄数
2:从区域的右端开始连续的未被摧毁的最大村庄数
3:包括区域中点的最大连续村庄数 
    //这个信息应该可以不保存

然后就是结点的更新与查找了,具体看代码的操作。

#include

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MAXN 50001

struct{
    int s;
    int s_left;
    int s_right;
}Node[MAXN<<2];

int c[MAXN];

void PushUp(int l,int r,int rt)
{
    int m=(l+r)>>1;
    Node[rt].s=Node[rt<<1].s_right+Node[rt<<1|1].s_left;
    Node[rt].s_left=Node[rt<<1].s_left;
    if(Node[rt<<1].s_left==m-l+1)
        Node[rt].s_left+=Node[rt<<1|1].s_left;
    Node[rt].s_right=Node[rt<<1|1].s_right;
    if(Node[rt<<1|1].s_right==r-m)
        Node[rt].s_right+=Node[rt<<1].s_right;
}

void build(int l,int r,int rt)
{
    Node[rt].s=r-1+1;
    Node[rt].s_left=r-l+1;
    Node[rt].s_right=r-l+1;
    if(l==r)
    {
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void update(int a,int tmp,int l,int r,int rt)
{
    if(l==r)
    {
        Node[rt].s=a;
        Node[rt].s_left=a;
        Node[rt].s_right=a;
        return;
    }
    int m=(l+r)>>1;
    if(tmp<=m)
        update(a,tmp,lson);
    else
        update(a,tmp,rson);
    PushUp(l,r,rt);
}

int query(int tmp,int l,int r,int rt)
{
    if(tmp-l+1<=Node[rt].s_left)
        return Node[rt].s_left;
    if(r-tmp+1<=Node[rt].s_right)
        return Node[rt].s_right;
    if(l==r)
        return Node[rt].s;
    int m=(l+r)>>1;
    if(tmp<=m)
        if(m-tmp+1<=Node[rt<<1].s_right)
            return Node[rt].s;
        else
            return query(tmp,lson);
    else
        if(tmp-m<=Node[rt<<1|1].s_left)
            return Node[rt].s;
        else
            return query(tmp,rson);
}

int main(void)
{
    int n,m,count,i,a;
    char ch[10];
//    freopen("d:\\in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        build(1,n,1);
        count=0;
        for(i=1;i<=m;i++)
        {
            scanf("%s",ch);
            if(ch[0]=='D')
            {
                scanf("%d",&a);
                c[++count]=a;
                update(0,a,1,n,1);
            }
            else if(ch[0]=='R')
            {
                if(count>0)
                    update(1,c[count--],1,n,1);
            }
            else
            {
                scanf("%d",&a);
                printf("%d\n",query(a,1,n,1));
            }
        }
    }
    return 0;
}



你可能感兴趣的:(ACM/线段树/单点更新)