Description
小Q在埃森哲工作想来也有日子了,表现非常突出,这不,最近team leader刚指派他带新来的小Y。
小Q总能在生活中找到游戏的乐趣,今天他决定跟小Y对一个区间集合进行游戏。
已知现在有一个包含N个区间的集合P = {[Li, Ri] 1 <= i <= N}。小Q首先选择一个区间[Li, Ri],然后她将所有满足(Li < Lj && Rj < Ri)的区间j从P集合中拿走组成一个新的集合A。
小Y作为后手,将在A集合中选择一个区间[Lu, Ru],并将A区间中所有满足(Lu < Lv && Rv < Ru)的区间v拿走组成一个新的区间B。游戏只进行一轮。
小Q希望游戏结束后|A| - |B|越大越好,而小Y则希望|B| - |A|越大越好。假设现在两人都使用最优策略,则最终|A| - |B|的值是多少?
Input
多组测试数据。
第1行:一个整数N(1 <= N <= 100,000)。
第2到N+1行:每行输入两个整数Li, Ri(0 <= Li <= Ri <= 1,000,000,000)。
Output
对于每组数据输出一行,包含一个整数,代表最终|A| - |B|的值。
Sample Input
41 52 43 33 3
Sample Output
2
HINT
|A|表示A集合中元素的个数。
如果,Alice选择[2, 4],则A = {[3, 3], [3, 3]},Bob在A集合中不管选谁,都只能得到空集,结果为2。
如果,Alice选择[1, 5], 则A = {[2, 4], [3, 3], [3, 3]},Bob选择[2, 4],则A = {[2, 4]}, B = {[3, 3], [3, 3]},结果为-1。
解题思路:要求求|A|-|B|的值,其实当你确定A区间后,|A|-|B|已经确定了。
1)先离散化输入的区间值,将结果保存在数组a中,然后排序,剔除a里面重复元素;
2)将输入的区间按右边界从小到大排序,如果右边界相等,按左边界从小到大排;
3)从a数组里面找到区间边界值,并将其更换为在a里面的序号;
4)经过以上处理后,扫描所有区间,应为区间已按右边界值排序,所以从左边扫描时
只需要统计比该区间左边界大的区间,得到的就是|A|,因为数据很大所以需要用树状 数组,|B|是在求完根据|A|后不断更新的;
说明:参考以下大神代码写的:大神博客链接,
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
#define M 100100
#define lowbit(x) (x&(-x))
struct Node
{
int l, r;
bool operator < (const Node &t) const
{
if(t.r==r) return l<t.l;
return r<t.r;
}
}node[M];
int a[M<<1];
int f[2][M<<1];
void update(int pos, int a)
{
while(pos)
{
f[1][pos] = max(f[1][pos], a);
f[0][pos] +=1;
pos -= lowbit(pos);
}
}
int solve(int pos, int &B)
{
int rec;
rec = B= 0;
while(pos<=2*M)
{
rec += f[0][pos];
B = max(B, f[1][pos]);
pos += lowbit(pos);
}
return rec;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
memset(f, 0, sizeof(f));
int l = 0;
for(int i=0; i<n; i++)
{
scanf("%d%d", &node[i].l, &node[i].r);
a[l++] = node[i].l; a[l++] = node[i].r; //离散化
}
sort(a, a+l);
sort(node, node+n);
l = unique(a, a+l)-a; //剔除a里面重复元素;
for(int i=0; i<n; i++)
{
node[i].l = lower_bound(a, a+l, node[i].l)-a+1; //求在a里面的对应序号;
node[i].r = lower_bound(a, a+l, node[i].r)-a+1;
}
int ans = -1111111111;
for(int i=0; i<n; i++)
{
int A, B;
A = solve(node[i].l, B); //计算A, B;
ans = max(ans, (A-B-B));
update(node[i].l-1, A); //更新状态数组;
}
printf("%d\n", ans);
}
return 0;
}