CF - 817F. MEX Queries - 离散化线段树

1.题目描述:

F. MEX Queries
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given a set of integer numbers, initially it is empty. You should perform n queries.

There are three different types of queries:

  • 1 l r — Add all missing numbers from the interval [l, r]
  • 2 l r — Remove all present numbers from the interval [l, r]
  • 3 l r — Invert the interval [l, r] — add all missing and remove all present numbers from the interval [l, r]

After each query you should output MEX of the set — the smallest positive (MEX  ≥ 1) integer number which is not presented in the set.

Input

The first line contains one integer number n (1 ≤ n ≤ 105).

Next n lines contain three integer numbers t, l, r (1 ≤ t ≤ 3, 1 ≤ l ≤ r ≤ 1018) — type of the query, left and right bounds.

Output

Print MEX of the set after each query.

Examples
input
3
1 3 4
3 1 6
2 1 3
output
1
3
1
input
4
1 1 3
3 5 6
2 4 4
3 1 6
output
4
4
4
1
Note

Here are contents of the set after each query in the first example:

  1. {3, 4} — the interval [3, 4] is added
  2. {1, 2, 5, 6} — numbers {3, 4} from the interval [1, 6] got deleted and all the others are added
  3. {5, 6} — numbers {1, 2} got deleted

2.题意概述:

初始数组为空,你有三种操作,第一种是把[l,r]区间数都添加进来,第二种是把[l,r]区间数都删除,第三种是把[l,r]区间数都反转(出现的数删除,未出现的数出现),每种操作要你输出在所有数构成的区间中未出现的最小值。

3.解题思路:

增加减少可以尝试线段树,因为l,r可以很大,而n才1e5,我们不能直接建树,考虑线段树的离散化,先离线读入所有出现过的数,再他们离散化,再去建树查询。然后考虑怎么做,我们可以初始标记为0表示都未出现,而出现的数就标记为1,那么对于操作1,实际上就是把[l,r]区间都变为1,而操作2就是变为0,那么维护一下区间和即可,如果这个区间是满的,和就是区间的宽度,操作三呢?把0变1,把1变0,实际上这种情况区间和就变成了“区间宽度-原区间和”。

4.AC代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 100010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
struct Query
{
	int op, l, r;
	ll ql, qr;
} q[maxn];
ll a[maxn << 2];
int cnt;
struct SegmentTree
{
	int l, r;
	ll val, tag;
} t[maxn << 4];
void pushup(int root)
{
	t[root].val = t[lson].val + t[rson].val;
}
void pushdown(int root)
{
	if (t[root].tag < 0)
		return;
	int mid = t[root].l + t[root].r >> 1;
	if (t[root].tag < 2)
	{
		t[lson].val = t[root].tag * (mid - t[root].l + 1);
		t[rson].val = t[root].tag * (t[root].r - mid);
		t[lson].tag = t[rson].tag = t[root].tag; 
	}
	else	//翻转
	{
		t[lson].val = mid - t[root].l + 1 - t[lson].val;
		t[rson].val = t[root].r - mid - t[rson].val;
		t[lson].tag = 1 - t[lson].tag;
		t[rson].tag = 1 - t[rson].tag;
	}
	t[root].tag = -1;
}
void build(int l, int r, int root)
{
	t[root].l = l;
	t[root].r = r;
	t[root].tag = -1;
	if (l == r)
	{
		t[root].val = 0;
		return;
	}
	int mid = l + r >> 1;
	build(l, mid, lson);
	build(mid + 1, r, rson);
	pushup(root);
}
void update(int op, int l, int r, int root)
{
	if (l <= t[root].l && t[root].r <= r)
	{
		if (op < 2)
		{
			t[root].val = (1 - op) * (t[root].r - t[root].l + 1);
			t[root].tag = 1 - op;
		}
		else
		{
			t[root].val = t[root].r - t[root].l + 1 - t[root].val;
			t[root].tag = 1 - t[root].tag;
		}
		return;
	}
	pushdown(root);
	int mid = t[root].l + t[root].r >> 1;
	if (l <= mid)
		update(op, l, r, lson);
	if (r > mid)
		update(op, l, r, rson);
	pushup(root);
}
int query(int root)
{
	if (t[root].l == t[root].r)
		return t[root].l;
	pushdown(root);
	int mid = t[root].l + t[root].r >> 1;
	if (t[lson].val < mid - t[root].l + 1)	//左侧出现了mix
		return query(lson);
	return query(rson);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	long _begin_time = clock();
#endif
	int n;
	while (~scanf("%d", &n))
	{
		cnt = 0;
		a[++cnt] = 1;
		for (int i = 1; i <= n; i++)	//离散化
		{
			scanf("%d%I64d%I64d", &q[i].op, &q[i].ql, &q[i].qr);
			a[++cnt] = q[i].ql;
			a[++cnt] = q[i].qr;
			a[++cnt] = q[i].qr + 1;
		}
		sort(a + 1, a + cnt + 1);
		cnt = unique(a + 1, a + cnt + 1) - (a + 1);
		build(1, cnt, 1);
		for (int i = 1; i <= n; i++)
		{
			q[i].l = lower_bound(a + 1, a + cnt + 1, q[i].ql) - a;
			q[i].r = lower_bound(a + 1, a + cnt + 1, q[i].qr) - a;
			update(q[i].op - 1, q[i].l, q[i].r, 1);
			printf("%I64d\n", a[query(1)]);
		}
	}
#ifndef ONLINE_JUDGE
	long _end_time = clock();
	printf("time = %ld ms.", _end_time - _begin_time);
#endif
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值