1. 程式人生 > >bzoj4548 小奇的糖果 掃描線+連結串列+樹狀陣列

bzoj4548 小奇的糖果 掃描線+連結串列+樹狀陣列

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; }