HDU - 1540(区间合并)

第一次做区间合并,对于这种保存区间的还是很不熟悉,向上更新的时候还是没有头绪。

区间合并的题目还是需要多写。

对于本题而言,就是求一个包含查询节点的连续区间的长度。

pushup的时候 需要注意的是,向上更新的时候,一个区间全是没被破坏的情况。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f

using namespace std;
int n , m;
int q;
const int maxn = 50000+10;
stack<int>st;
struct SegTree
{
    int lx,rx,mx,l,r;
}t[maxn << 2];

void build(int l,int r,int i)
{
    t[i].l = l;t[i].r = r;t[i].lx = t[i].rx = t[i].mx = r-l+1;
//    cout << "WWWW: " << t[i].mx << endl;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
}

void pushup(int i)
{
    t[i].lx = t[i<<1].lx;
    t[i].rx = t[i<<1|1].rx;
    t[i].mx = max(t[i<<1].mx , t[i<<1|1].mx);
    t[i].mx = max(t[i].mx , t[i<<1].rx + t[i<<1|1].lx);
    if(t[i<<1].lx == t[i<<1].r - t[i<<1].l + 1)
        t[i].lx +=  t[i<<1|1].lx;
    if(t[i<<1|1].rx == t[i<<1|1].r - t[i<<1|1].l + 1 )
        t[i].rx +=  t[i<<1].rx;
//    cout << "AAAAA:  " << t[i].mx << endl;
}

void update(int t1, int i, int val)
{
    if(t[i].l == t[i].r)
    {
        if(val == 1)
        {
            t[i].lx = t[i].rx = t[i].mx = 1;
        }
        else
        {
            t[i].lx = t[i].rx = t[i].mx = 0;
        }
//        cout << t[i].l << "*****" << t[i].lx << endl;
        return ;
    }
    int mid = (t[i].l + t[i].r) / 2;
    if(t1 <= mid) update(t1,i<<1,val);
    if(t1 >  mid) update(t1,i<<1|1,val);
    pushup(i);
}

int query(int t1, int i)
{
//    if(t[i].l==3 && t[i].r == 4) cout << " YES " << t[i].mx << endl;
    if(t[i].l == t[i].r || t[i].mx == 0 || t[i].mx == t[i].r - t[i].l + 1)
    {
        return t[i].mx;
    }

    int mid = (t[i].l + t[i].r) >> 1;
//    cout << "LR: " << t[i].l  << " " << t[i].r << endl;
    if(t1 <= mid)
    {
        if(t1 >= t[i<<1].r - t[i<<1].rx + 1)
        {
//            cout << "A" <<endl;
            return  query(t1,i<<1) +query(mid+1,i<<1|1);
        }
        else
        {
//            cout << "B" <<endl;
            return query(t1,i<<1);
        }
    }
    else
    {
//        cout << "T1 : " << t1 << "  " << t[i<<1|1].lx + t[i<<1|1].l - 1 << endl;
        if(t1 <= t[i<<1|1].lx + t[i<<1|1].l - 1)
        {
//            cout << "C" <<endl;
            return query(t1,i<<1|1) + query(mid , i<<1);
        }
        else
        {
//            cout << "D" <<endl;
//            cout << " %%%%%% " << t[i<<1|1].l << " " << t[i<<1|1].r << " " << t1 << endl;
            return query(t1,i<<1|1);
        }
    }
}
int main()
{
    char ch;
    int k;
    while(cin >> n >> m)
    {
        while(!st.empty())
        {
            st.pop();
        }
        build(1,n,1);
        for(int i = 0 ; i < m ; i++)
        {
            cin >> ch;
            if(ch == 'D')
            {
                cin >> k;
                st.push(k);
//                cout << "k :" << "|" << k << "|" << endl;
//                cout << st.top() << endl;
                update(k,1,0);
            }
            else if(ch == 'R')
            {
                if(st.empty()) continue;
                int p = st.top();st.pop();
//                cout << "R :" << "|" << p << "|" << endl;
                update(p,1,1);
            }
            else
            {
                cin >> k;
                cout << query(k,1) << endl;
            }
        }
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值