您的位置:首页 > 其它

【BZOJ-4548&3658】小奇的糖果&Jabberwocky 双向链表 + 树状数组

2016-08-17 22:42 357 查看

4548: 小奇的糖果

Time Limit: 10 Sec Memory Limit: 256 MB
Submit:
103 Solved: 47
[Submit][Status][Discuss]

Description

有 N 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾

起多少糖果,使得获得的糖果并不包含所有的颜色。

Input

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

接下来 T 组测试数据,对于每组测试数据,第一行输入两个正整数 N、K,分别表示点数和颜色数。
接下来 N 行,每行描述一个点,前两个数 x, y (|x|, |y| ≤ 2^30 - 1) 描述点的位置,最后一个数 z (1 ≤ z

k) 描述点的颜色。
对于 100% 的数据,N ≤ 100000,K ≤ 100000,T ≤ 3

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

HINT

Source

By Hzwer

3658: Jabberwocky

Time Limit: 20 Sec Memory Limit: 1024 MB
Submit:
178 Solved: 73
[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

HINT

N<=100000,K<=100000,T<=3

Source

Solution

思路比较好的题,本来以为可以转化成某种扫描线,但是无果

首先,按y坐标排序,我们假定这条线无限低,这时候答案相当于相邻两个同种颜色的中间的最大点数

然后这条线向上,一次性删除一行

用双向链表维护一个点的前一个和后一个同种颜色的位置

删除的话,把这个点从树状数组和链表中都删除,每次删除,统计一下这个点之前相邻的和之后相邻的答案

然后把y全都赋成相反数,再做一遍即可得到下端的情况

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 1000010
int T,N,K,ans;
struct PointNode{int x,y,c,id;}P[MAXN];
int ls[MAXN],tp,top;
struct lkList{int last,nxt,now;}lk[MAXN];
int C[MAXN];
struct BIT
{
int tree[MAXN];
void Init() {memset(tree,0,sizeof(tree));}
int lowbit(int x) {return x&(-x);}
void Add(int pos,int D)
{
for (int i=pos; i<=top+1; i+=lowbit(i))
tree[i]+=D;
}
int Query(int pos)
{
int re=0;
for (int i=pos; i; i-=lowbit(i))
re+=tree[i];
return re;
}
int Query(int L,int R) {if (R<L) return 0; else return Query(R)-Query(L-1);}
}bit;
bool cmpY(PointNode A,PointNode B) {return A.y<B.y;}
bool cmpX(PointNode A,PointNode B) {return A.x<B.x;}
void Solve()
{
bit.Init();
memset(C,0,sizeof(C));
sort(P+1,P+N+1,cmpX); lk[N+1].now=top+1;
for (int i=1; i<=N; i++) bit.Add(P[i].x,1);
for (int i=1; i<=N; i++)
{
P[i].id=i;
lk[i].last=C[ P[i].c ]; lk[i].nxt=N+1; lk[i].now=P[i].x;
if (C[ P[i].c ]) lk[ C[ P[i].c ] ].nxt=i;
C[ P[i].c ]=i;
ans=max(ans,bit.Query(P[ lk[i].last ].x+1,P[i].x-1));
}
//  printf("Ans1=%d\n",ans);
sort(P+1,P+N+1,cmpY);
for (int i=1; i<=K; i++)
ans=max(ans,bit.Query(lk[ C[i] ].now+1,top+1));
//  printf("Ans2=%d\n",ans);
for (int t=1,i=1; i<=N; i++)
{
int now=P[i].id;
while (t<=N && P[t].y==P[i].y)
bit.Add(P[t].x,-1),t++;
if (lk[now].nxt) lk[ lk[now].nxt ].last=lk[now].last;
if (lk[now].last) lk[ lk[now].last ].nxt=lk[now].nxt;
ans=max(ans,bit.Query(lk[ lk[now].last ].now+1,lk[ lk[now].nxt ].now-1));
lk[now].nxt=lk[now].last=0;
}
//  printf("Ans3=%d\n",ans);
}
int main()
{
T=read();
while (T--)
{
N=read(),K=read();
ans=0;
for (int i=1; i<=N; i++)
ls[++tp]=P[i].x=read(),P[i].y=read(),P[i].c=read(),P[i].id=i;
sort(ls+1,ls+tp+1);
top=unique(ls+1,ls+tp+1)-ls-1;
for (int i=1; i<=N; i++) P[i].x=lower_bound(ls+1,ls+top+1,P[i].x)-ls;
//for (int i=1; i<=N; i++) printf("x=%d\n",P[i].x);
Solve();
for (int i=1; i<=N; i++) P[i].y=-P[i].y;
Solve();
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: