bzoj4548 小奇的糖果 扫描线+链表+树状数组

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/84894399

Description


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

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

Solution


一开始以为是一条直线。。原来是线段

不包含所有颜色就把某一种颜色抠出来统计答案。我们用链表维护同色点的前驱和后继,然后扫描线删点的时候更新答案就可以了

一开始挂了是因为没有算原图的答案quq

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))
#define lowbit(x) (x&-x)

const int N=100005;

struct data {int x,y,col;} d[N];

int n,m,c[N],l[N],r[N],b[N];
int rec[N],tmpl[N],tmpr[N],rank[N];

bool vis[N];

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

void add(int x,int v) {
	for (;x<=n;x+=lowbit(x)) c[x]+=v;
}

int get(int x) {
	int res=0;
	for (;x;x-=lowbit(x)) res+=c[x];
	return res;
}

bool cmpx(data d,data b) {
	return (d.x==b.x)?(d.y<b.y):(d.x<b.x);
}

bool cmpy(int p,int q) {
	return (d[p].y==d[q].y)?(d[p].x<d[q].x):(d[p].y<d[q].y);
}

int solve() {
	int ans=0;
	std:: sort(d+1,d+n+1,cmpx);
	fill(rec,0);
	rep(i,1,n) {
		l[i]=rec[d[i].col];
		rec[d[i].col]=i;
	}
	fill(rec,0);
	drp(i,n,1) {
		r[i]=rec[d[i].col]; r[i]=!r[i]?(n+1):r[i];
		rec[d[i].col]=i;
	}
	fill(c,0);
	rep(i,1,n) rank[i]=i,add(d[i].x,1);
	rep(i,1,n) ans=std:: max(ans,get(d[i].x-1)-get(d[l[i]].x));
	rep(i,1,n) ans=std:: max(ans,get(d[r[i]].x-1)-get(d[i].x));
	ans=std:: max(ans,get(n)-get(d[n].x));
	std:: sort(rank+1,rank+n+1,cmpy);
	for (int st=1,ed;st<=n;st=ed+1) {
		int y=d[rank[st]].y;
		for (ed=st;ed<n&&d[rank[ed+1]].y==y;) ed++;
		rep(i,st,ed) add(d[rank[i]].x,-1);
		rep(i,st,ed) {
			if (d[l[rank[i]]].y==y) tmpl[i]=rec[d[rank[i]].col];
			else tmpl[i]=l[rank[i]],rec[d[rank[i]].col]=tmpl[i];
		}
		drp(i,ed,st) {
			if (d[r[rank[i]]].y==y) tmpr[i]=rec[d[rank[i]].col];
			else tmpr[i]=r[rank[i]],rec[d[rank[i]].col]=tmpr[i];
		}
		rep(i,st,ed) ans=std:: max(ans,get(d[tmpr[i]].x-1)-get(d[tmpl[i]].x));
		rep(i,st,ed) {
			int x=rank[i];
			l[r[x]]=l[x],r[l[x]]=r[x];
		}
	}
	return ans;
}

int main(void) {
	for (int T=read(),cnt;T--;) {
		fill(vis,0); cnt=0;
		n=read();m=read();
		rep(i,1,n) {
			d[i].x=read(),d[i].y=read();
			d[i].col=read(),vis[d[i].col]=1;
			b[++cnt]=d[i].x;
		}
		bool flag=false;
		rep(i,1,m) flag|=(!vis[i]);
		if (flag) {
			printf("%d\n",n);
			continue;
		}
		std:: sort(b+1,b+cnt+1);
		cnt=std:: unique(b+1,b+cnt+1)-b-1;
		rep(i,1,n) d[i].x=std:: lower_bound(b+1,b+cnt+1,d[i].x)-b;
		cnt=0;
		rep(i,1,n) b[++cnt]=d[i].y;
		std:: sort(b+1,b+cnt+1);
		cnt=std:: unique(b+1,b+cnt+1)-b-1;
		rep(i,1,n) d[i].y=std:: lower_bound(b+1,b+cnt+1,d[i].y)-b;
		int ans=0;
		d[0].x=0;d[n+1].x=n+1;
		ans=std:: max(ans,solve());
		rep(i,1,n) d[i].y=n-d[i].y+1;
		ans=std:: max(ans,solve());
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/84894399
今日推荐