Description
Input
output
Sample Input
7 11
1 15
1 123123
1 3
1 5
2 123123
2 15
1 21
2 3
1 6
1 7
1 8
Sample Output
1
7
4
2
7
4
1
3
做法:可以考虑线段树。首先我们对区间[1..n]建立一棵线段树。对于每一个节点,
维护 4 个值。分别是 l,r,mid,p。l 表示在当前结点线段树所在区间最左边的花精
所在的位置,r 表示最右边的花精所在的位置。mid 表示在这个小区间[l,r]中的
两只花精之间的最长距离除以 2 后的值。p 表示取 mid 值时所在的紧邻的两只
花精的中间位置,也就是在[l,r]中的答案值。
对于 1 询问:访问线段树的第一个节点,我们比较 l-1,n-r,mid 的值哪
个更大,就选哪个,它们的答案依次是 1,n,p。假设我们求得的位置是 fairy[x]。
然后访问[fairy[x],fairy[x]]所在的线段树的叶子节点,初始化它的值,然后回溯,
进行合并。对于 tr[x].l 与 tr[x].r 可以通过两个儿子的 l,r 信息得出。对于 tr[x].mid
值,首先在左右儿子的 mid 值中去一个最大的值。其次考虑一种情况,就是夹在
两个线段之间的距离,可以通过(tr[x+x+1].l-tr[x+x].r) / 2 的值得出在于 mid
进行比较,然后 p 就随着 mid 的值的更新而更新。
对于 2 询问:访问询问花精所在的位置,直接将它的叶子节点
[fairy[x],fairy[x]]删除,然后回溯时,再做一次合并操作。
细节蛮多的。。。
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#define N 1000007
using namespace std;
struct tree
{
int l, r, mid, p;
}f[N];
int n, m, a[N];
int read()
{
int s = 0;
char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s;
}
void update(int x)
{
if (f[x << 1].l > 0) f[x].l = f[x << 1].l;
else f[x].l = f[x << 1 | 1].l;
if (f[x << 1 | 1].r > 0) f[x].r = f[x << 1 | 1].r;
else f[x].r = f[x << 1].r;
f[x].mid = f[x << 1].mid;
f[x].p = f[x << 1].p;
if (f[x << 1].r > 0 && f[x << 1 | 1].l > 0)
{
int cmp = (f[x << 1 | 1].l - f[x << 1].r) / 2;
if (cmp > f[x].mid)
{
f[x].mid = cmp;
f[x].p = (f[x << 1].r + f[x << 1 | 1].l) / 2;
}
if (f[x << 1 | 1].mid > f[x].mid)
{
f[x].mid = f[x << 1 | 1].mid;
f[x].p = f[x << 1 | 1].p;
}
}
}
void change(int p, int l, int r, int x, int judge)
{
if (l == r)
{
if (judge == 2)
{
f[p].l = 0;
f[p].r = 0;
f[p].p = 0;
f[p].mid = 0;
}
else
{
f[p].l = l;
f[p].r = r;
f[p].p = 0;
f[p].mid = 0;
}
return;
}
int mid = (l + r) / 2;
if (x <= mid) change(p << 1, l, mid, x, judge);
else change(p << 1 | 1, mid + 1, r, x, judge);
update(p);
}
int main()
{
n = read(), m = read();
int x, y;
while (m--)
{
y = read(), x = read();
if (y == 1)
{
if (f[1].l == 0) a[x] = 1;
else
{
int cmp = -2000000;
if (f[1].l - 1 > cmp)
{
cmp = f[1].l - 1;
a[x] = 1;
}
if (f[1].mid > cmp)
{
cmp = f[1].mid;
a[x] = f[1].p;
}
if (n - f[1].r > cmp)
{
cmp = n - f[1].r;
a[x] = n;
}
}
printf("%d\n", a[x]);
change(1, 1, n, a[x], 1);
}
else change(1, 1, n, a[x], 2);
}
}