bzoj 4548 小奇的糖果
他要求不包含所有颜色,那我们可以强制某种颜色不被包含.枚举每一种颜色,然后按纵坐标从小到大排序.枚举到一个点,我们要考虑在它下面一点的线段能取的最大的区域,那么左右端点分别是之前加入了的纵坐标更小离他最近的点,这个可以用以横坐标为关键字的set找.另外要把上面没有这种点的线段与下面点构成的区域也加进来.这里只考虑了往下取,可以所有点纵坐标颠倒后再来一次,就求出所有可选的矩形区域,然后扫描线二维数点
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=3e5+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n,kk,q,ans,sq[N];
int bx[N],mx,by[N],my;
int bt[N];
void add(int x,int y){while(x<=mx) bt[x]+=y,x+=x&(-x);}
int gsm(int x){int an=0;while(x) an+=bt[x],x-=x&(-x);return an;}
struct node
{
int x,y;
bool operator < (const node &bb) const {return y!=bb.y?y<bb.y:x<bb.x;}
}a[N];
vector<int> st[N];
int stk[N],tp;
bool cmp(int aa,int bb){return a[aa]<a[bb];}
set<int> sb;
set<int>::iterator ft,nt;
struct qq
{
int l,r,y;
bool operator < (const qq &bb) const {return y<bb.y;}
}qr[N<<1];
void wk()
{
q=0;
for(int i=1;i<=kk;++i)
{
if(st[i].empty()){ans=n;break;}
sb.clear(),sb.insert(1),sb.insert(mx);
sort(st[i].begin(),st[i].end(),cmp);
vector<int>::iterator it;
int las=-1;
tp=0;
for(it=st[i].begin();it!=st[i].end();++it)
{
int j=*it;
if(a[j].y!=las)
{
las=a[j].y;
while(tp)
sb.insert(a[stk[tp]].x),--tp;
}
nt=sb.upper_bound(a[j].x);
ft=--nt,++nt;
if(*ft!=a[j].x)
{
qr[++q]=(qq){(*ft)+1,(*nt)-1,a[j].y-1};
stk[++tp]=j;
}
}
while(tp)
sb.insert(a[stk[tp]].x),--tp;
ft=sb.begin(),nt=++ft,--ft;
for(;nt!=sb.end();++ft,++nt)
qr[++q]=(qq){(*ft)+1,(*nt)-1,my-1};
}
sort(qr+1,qr+q+1);
for(int i=1;i<=n+1;++i) sq[i]=i;
a[n+1].y=my+1;
sort(sq+1,sq+n+2,cmp);
memset(bt,0,sizeof(int)*(mx+1));
for(int i=1,j=1,k=1;i<=n+1;++j)
{
while(k<=q&&qr[k].y<a[sq[i]].y)
{
ans=max(ans,gsm(qr[k].r)-gsm(qr[k].l-1));
++k;
}
while(j<=n&&a[sq[j+1]].y==a[sq[j]].y) ++j;
while(i<=j) add(a[sq[i]].x,1),++i;
}
}
int main()
{
int T=rd();
while(T--)
{
n=rd(),kk=rd();
for(int i=1;i<=kk;++i) st[i].clear();
mx=my=0;
bx[++mx]=-2147483648,bx[++mx]=2147483647;
by[++my]=-2147483648,by[++my]=2147483647;
for(int i=1;i<=n;++i)
{
a[i].x=rd()*2,a[i].y=rd()*2;
bx[++mx]=a[i].x,bx[++mx]=a[i].x-1,bx[++mx]=a[i].x+1;
by[++my]=a[i].y,by[++my]=a[i].y-1,by[++my]=a[i].y+1;
st[rd()].push_back(i);
}
sort(bx+1,bx+mx+1),mx=unique(bx+1,bx+mx+1)-bx-1;
for(int i=1;i<=mx;++i) a[i].x=lower_bound(bx+1,bx+mx+1,a[i].x)-bx;
sort(by+1,by+my+1),my=unique(by+1,by+my+1)-by-1;
for(int i=1;i<=my;++i) a[i].y=lower_bound(by+1,by+my+1,a[i].y)-by;
ans=0;
wk();
for(int i=1;i<=n;++i) a[i].y=my-a[i].y+1;
wk();
printf("%d\n",ans);
}
return 0;
}
彩蛋
本题题意应该是~~有 N 个彩色糖果在平面上。小奇想在平面上取一条**直线**,并拾起它上方或下方的所有糖果。求出最多能够拾起多少糖果,使得获得的糖果并不包含**相同**的颜色。~~其实是我看错了qwq