有 N 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾
起多少糖果,使得获得的糖果并不包含所有的颜色。
有 N 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾
包含多组测试数据,第一行输入一个正整数 T 表示测试数据组数。
对于每组数据在一行内输出一个非负整数 ans,表示答案
By Hzwer
题解:线段树+树状数组
分成三种情况统计答案。该点与在该点下方的相同颜色的前驱后继围成的区域,该点与该点上方的相同颜色的前驱后继围成的区域,已经相邻最近的两个相同颜色之间的区域。
前驱后继可以用线段树维护,然后清数组的时候用lazy标记。
统计答案的时候用树状数组,如果统计下方的,就按照纵坐标从小到大向树状数组中该点对应的横坐标的位置加点,然后统计该点下方,在前驱后继之间的点。
统计上方反过来即可。
统计相邻两个之间的点,刚开始直接把所以点加入树状数组,然后查询两点之间的区域即可。
#include
#include
#include
#include
#include
#define N 500003
using namespace std;
int n,m,cnt,tree[N],T,ans;
int tr[N],b[N],c[N],delta[N],tr1[N],delta1[N];
int next[N],head[N];
struct point
{
int x,y,num,col;
int pre,next,ans;
}a[N];
int cmp(int x,int y)
{
return c[x]cnt) return ;
if (l==r)
{
tr[now]=l;
return;
}
pushdown(now);
int mid=(l+r)/2;
if (x<=mid) change(now<<1,l,mid,x);
else change(now<<1|1,mid+1,r,x);
update(now);
}
int find(int now,int l,int r,int ll,int rr)
{
if (rrmid) ans=max(ans,find(now<<1|1,mid+1,r,ll,rr));
return ans;
}
void clear1(int now)
{
delta1[now]=1;
tr1[now]=cnt+1;
}
void pushdown1(int now)
{
if (delta1[now])
{
delta1[now]=0;
clear1(now<<1); clear1(now<<1|1);
}
}
void update1(int now)
{
tr1[now]=min(tr1[now<<1],tr1[now<<1|1]);
}
void change1(int now,int l,int r,int x)
{
if (x<0||x>cnt) return;
if (l==r)
{
tr1[now]=l;
return;
}
pushdown1(now);
int mid=(l+r)/2;
if (x<=mid) change1(now<<1,l,mid,x);
else change1(now<<1|1,mid+1,r,x);
update1(now);
}
int find1(int now,int l,int r,int ll,int rr)
{
if (rrmid) ans=min(ans,find1(now<<1|1,mid+1,r,ll,rr));
return ans;
}
int cmp2(point x,point y)
{
return x.y=1;i-=lowbit(i))
ans+=tree[i];
return ans;
}
void add(int x)
{
for (int i=x;i<=cnt;i+=lowbit(i))
tree[i]++;
}
int cmp5(point x,point y)
{
return x.x=l) ans=max(ans,sum(r-1)-sum(l));
head[a[i].col]=a[i].x;
}
for (int i=1;i<=m;i++)
if(head[i]<=n)
ans=max(ans,sum(cnt)-sum(head[i]));
//cout<