线段树

线段树区间合并
点击此处进入题目

#include <bits/stdc++.h>

#define int long long

using namespace std;
int n,m;
const int N = 50010;
int temp[N];
struct node
{
    int l,r,lmax,rmax,tmax;
}tr[N * 4];

void pushup(node &root ,node &left, node &right)
{
    root.lmax = left.lmax;
    root.rmax = right.rmax;
    
    if(left.lmax == left.r - left.l + 1) root.lmax += right.lmax;
    if(right.rmax == right.r - right.l + 1) root.rmax += left.rmax;
    
    root.tmax = max(max(left.tmax , right.tmax), left.rmax + right.lmax);
}

void pushup(int u)
{
    pushup(tr[u] , tr[u << 1], tr[u << 1 | 1]);
}

void build(int u,int l,int r)
{
    if(l == r) tr[u] = {r , r, 1, 1, 1};
    else
    {
        tr[u] = {l , r};
        int mid = l + r >> 1;
        build(u << 1, l , mid);
        build(u << 1|1, mid + 1 , r);
        pushup(u);
    }
}

void modify(int u,int x,int c)
{
    if(tr[u].l == x && tr[u].r == x) tr[u] = {x,x,c,c,c};
    else
    {
        int mid = tr[u].l + tr[u].r >> 1;
        if(x <= mid) modify(u << 1, x , c);
        else modify(u << 1 | 1, x ,c);
        pushup(u);
    }
}

int query(int u,int x) {
	if (tr[u].tmax == 0 || tr[u].l == tr[u].r) return tr[u].tmax;
	
	int mid = tr[u].l + tr[u].r >> 1;
	if (x <= mid)
	{
		if (mid - x + 1 <= tr[u << 1].rmax) return tr[u << 1].rmax + tr[u << 1 | 1].lmax; 
		else return  query(u << 1, x); 
	} 
	else 
	{
		if (x - mid <= tr[u << 1 | 1].lmax)  return tr[u << 1].rmax + tr[u << 1 | 1].lmax;
		else return query(u << 1 | 1, x); 
	} 
}

signed main()
{
    while(cin >> n >> m)
    {
        memset(temp,0,sizeof temp[0] * n);
        memset(tr ,0 ,sizeof tr[0] * 4 * n);
        
        build(1,1,n);
        int cnt = 0;
        while(m --)
        {
            char s; int x;
            cin >> s;
            if(s == 'D')
            {
                cin >> x;
                modify(1,x,0);
                temp[ ++ cnt] = x;
            }
            else if(s == 'Q')
            {
                cin >> x;
                cout << query(1,x) << endl;
            }
            else  if(cnt > 0) modify(1,temp[cnt --],1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值