您的位置:首页 > 其它

bzoj 4548: 小奇的糖果 && bzoj 3658: Jabberwocky(双向链表+树状数组)

2017-08-12 02:33 281 查看

3658: Jabberwocky

Time Limit: 20 Sec  Memory Limit: 1024 MB
Submit: 263  Solved: 107

[Submit][Status][Discuss]

Description

平面上有n个点,每个点有k种颜色中的一个。

你可以选择一条水平的线段获得在其上方或其下方的所有点,如图所示:



请求出你最多能够得到多少点,使得获得的点并不包含所有的颜色。

   

Input

包含多组测试数据,第一行输入一个数T表示测试数据组数。

接下来T组测试数据,对于每组测试数据,第一行输入两个数n,k,分别表示点的个数和颜色数。

接下来n行每行描述一个点,前两个数z,y(lxl,lyl≤2^32-1)描述点的位置,最后一个数z(1≤z≤K)描述点的颜色。

Output

 对于每组数据输出一行,每行一个数ans,表示答案。

Sample Input

1

10 3

1 2 3

2 1 1

2 4 2

3 5 3

4 4 2

5 1 2

6 3 1

6 7 1

7 2 3

9 4 2

Sample Output

5

将问题简化:

假设线段只有可能在在坐标系的最下面or最上面,并且每个x坐标都不同

那么只要用双向链表O(n)模拟一下就好了,所有坐标点按x大小排序,第p个节点就是从小到大第p个坐标

每个节点p记录一个p.pre和p.next,分别表示在左边or右边颜色相同且离得最近的节点id,

答案就是max(max(p.next-1-p, p-1-p.pre))  (1<=p<=n),也就是两个相邻的相同颜色节点之间距离的最大值

如果存在x坐标相同的点

要先将x坐标离散化,并且上面的那个式子就会有问题,因为x坐标相同的点只有可能同时取或同时不取

这样就不能直接求p.next和p的间隔了,而是找到x坐标刚好小于p.next点以及x坐标刚好大于p点的两点之间有多少个点,求这个的最大值,因为离散化过了,这个很好处理

p和p.pre之间同理

显然这题线段没有限制,不一定在最下面or最上面

那样的话我们需要按y坐标从小到大排序(如果相同再按x排序)

求出来上面的东西之后再从下到上扫描,逐个删点,每删一个点求一次最大值

因为是双向链表,所以删点是O(1)的,并且只有这段变大的区间会影响答案

不过因为中间有些点已经消失了,所以不能直接通过相减求间隔,要用树状数组保存哪些还没有被删

别忘了还要从上往下再来一次

总复杂度O(n)+O(2nlogn)=O(nlogn)

注意这题有个坑,假设有k种颜色但是下面出现的不同颜色数量都不到k个,那么答案就是n(也就是所有点全部选中)还有bzoj3658这题的数据比较强,虽然是一模一样的题,但一开始我4548AC了,3658WA,不是long long的问题

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL long long
typedef struct
{
LL pre;
LL nxt;
}Line;
Line h[100005];
typedef struct Res
{
LL x, y;
LL id;
LL col;
bool operator < (const Res &b) const
{
if(id<b.id)
return 1;
return 0;
}
}Res;
Res s[100005];
LL cnt, Hash[100005], tre[100005], temp[100005], y[100005], col[100005];
bool compx(Res a, Res b)
{
if(a.x<b.x)
return 1;
return 0;
}
bool compy(Res a, Res b)
{
if(a.y<b.y || a.y==b.y && a.x<b.x)
return 1;
return 0;
}
void Update(LL x, LL val)
{
while(x<=cnt)
{
tre[x] += val;
x += x&-x;
}
}
LL Query(LL x)
{
LL sum = 0;
while(x)
{
sum += tre[x];
x -= x&-x;
}
return sum;
}
int main(void)
{
LL T, i, n, m, ans;
scanf("%lld", &T);
while(T--)
{
cnt = 0;
scanf("%lld%lld", &n, &m);
memset(col, 0, sizeof(col));
for(i=1;i<=n;i++)
{
scanf("%lld%lld%lld", &s[i].x, &s[i].y, &s[i].col);
s[i].id = i;
Hash[++cnt] = s[i].x;
col[s[i].col] = 1;
}
for(i=1;i<=m;i++)
{
if(col[i]==0)
break;
}
if(i<=m)
{
printf("%lld\n", n);
continue;
}
sort(Hash+1, Hash+cnt+1);
cnt = unique(Hash+1, Hash+cnt+1)-(Hash+1);
s[n+1].x = cnt+1;
for(i=1;i<=n;i++)
s[i].x = lower_bound(Hash+1, Hash+cnt+1, s[i].x)-Hash;

ans = 0;
sort(s+1, s+n+1, compx);
memset(temp, 0, sizeof(temp));
for(i=1;i<=n;i++)
{
Update(s[i].x, 1);
h[i].pre = temp[s[i].col];
s[i].id = i;
temp[s[i].col] = i;
ans = max(ans, Query(s[i].x-1)-Query(s[h[i].pre].x));
}
for(i=1;i<=n;i++)
temp[i] = n+1;
for(i=n;i>=1;i--)
{
h[i].nxt = temp[s[i].col];
temp[s[i].col] = i;
ans = max(ans, Query(s[h[i].nxt].x-1)-Query(s[i].x));
}
sort(s+1, s+n+1, compy);
for(i=1;i<=n;i++)
y[i] = s[i].id;
sort(s+1, s+n+1);
for(i=1;i<=n;i++)
{
Update(s[y[i]].x, -1);
ans = max(ans, Query(s[h[y[i]].nxt].x-1)-Query(s[h[y[i]].pre].x));
h[h[y[i]].nxt].pre = h[y[i]].pre;
h[h[y[i]].pre].nxt = h[y[i]].nxt;
}

sort(s+1, s+n+1, compx);
memset(temp, 0, sizeof(temp));
for(i=1;i<=n;i++)
{
Update(s[i].x, 1);
h[i].pre = temp[s[i].col];
s[i].id = i;
temp[s[i].col] = i;
ans = max(ans, Query(s[i].x-1)-Query(s[h[i].pre].x));
}
for(i=1;i<=n;i++)
temp[i] = n+1;
for(i=n;i>=1;i--)
{
h[i].nxt = temp[s[i].col];
temp[s[i].col] = i;
ans = max(ans, Query(s[h[i].nxt].x-1)-Query(s[i].x));
}
sort(s+1, s+n+1, compy);
for(i=1;i<=n;i++)
y[i] = s[i].id;
sort(s+1, s+n+1);
for(i=n;i>=1;i--)
{
Update(s[y[i]].x, -1);
ans = max(ans, Query(s[h[y[i]].nxt].x-1)-Query(s[h[y[i]].pre].x));
h[h[y[i]].nxt].pre = h[y[i]].pre;
h[h[y[i]].pre].nxt = h[y[i]].nxt;
}
printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: