1.题目描述:
You are given a set of integer numbers, initially it is empty. You should perform n queries.
There are three different types of queries:
After each query you should output MEX of the set — the smallest positive (MEX ≥ 1) integer number which is not presented in the set.
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.
Print MEX of the set after each query.
3 1 3 4 3 1 6 2 1 3
1 3 1
4 1 1 3 3 5 6 2 4 4 3 1 6
4 4 4 1
Here are contents of the set after each query in the first example:
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;
}