【Codeforces 650E】Clockwork Bomb
【Codeforces 633H】Fibonacci-ish II

【Codeforces 650D】Zip-line

Zarxdy34 posted @ 2016年3月12日 18:32 in Codeforces with tags 线段树 LIS , 702 阅读

  先把所有的高度(包括询问里面修改后的高度)离散化。

  第一步先求出LIS。接下来要做的就是对于每次查询(a,b),快速求出修改后的LIS。

  然后我们可以考虑a这个点在上升序列中时的LIS,以及a不在序列中时的LIS。

  当a在序列中时,答案为\(\max \{ le{n_l}[i],i < a\ and\ h[i] < h[a]\}  + \max \{ le{n_r}[i],i > a\ and\ h[i] > h[a]\}  + 1\),其中\(le{n_l}[i]\)表示前i个数以第i个数为结尾时的LIS,\(le{n_r}[i]\)表示第i到第n个数以第i个数为开头的LIS。这个用线段树什么的维护一下就好了。为了支持删除操作,必要的时候还要开个队列来维护。

  对于第二种情况,显然只需判断第a个数对于原序列的LIS是不是必须的。如果是必须的,那么它要满足两个条件:1.\(\max \{ le{n_l}[i],i < a\ and\ h[i] < h[a]\}  + \max \{ le{n_r}[i],i > a\ and\ h[i] > h[a]\}  + 1\)等于原序列LIS长度;2.不存在满足条件一的i,使得\(le{n_l}[i] = le{n_l}[a]\)。(如果有,那么a可以被这个i取代)

  然后对两种情况下的答案取最大值,即为当前答案。询问需要事先按a排序,然后可以维护线段树。

 

#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=400010,inf=~0U>>1;

struct Querys
{
	int a,b,id;
}qur[maxn];

struct Segment_Tree
{
	int head[maxn<<3],next[maxn<<3],F[maxn<<3],Ecnt;
	int maxh[maxn<<3];
	int n;

	#define ls (o<<1)
	#define rs (o<<1|1)
	#define mid ((l+r)>>1)

	void Update(int o) {maxh[o]=max(maxh[ls],maxh[rs]);}

	void Change(int o,int l,int r,int pos,int c)
	{
		if (l==r) {maxh[o]=c;return;}
		if (pos<=mid) Change(ls,l,mid,pos,c);
		if (pos> mid) Change(rs,mid+1,r,pos,c);
		Update(o);
	}

	int Query(int o,int l,int r,int a,int b)
	{
		if (a<=l && r<=b) return maxh[o];
		int res=0;
		if (a<=mid) res=max(res,Query(ls,l,mid,a,b));
		if (b> mid) res=max(res,Query(rs,mid+1,r,a,b));
		return res;
	}
	#undef ls
	#undef rs
	#undef mid

	int Query(int a,int b) {if (b<a) return 0;return Query(1,1,n,a,b);}
	void Change(int x,int c) {Change(1,1,n,x,c);}
	void Insert(int x,int c) {if (head[x] && F[head[x]]>c) return;next[++Ecnt]=head[x];head[x]=Ecnt;F[Ecnt]=c;Change(x,c);}
	void Delete(int x,int c) {if (head[x]==0 || F[head[x]]!=c) return;head[x]=next[head[x]];Change(x,F[head[x]]);}
	void Clear() {memset(maxh,0,sizeof(maxh));memset(head,0,sizeof(head));Ecnt=0;}
}Tl,Tr;

int h[maxn];
int ht[maxn<<1],hs;
map <int,int> M;
int fl[maxn],fr[maxn];
int keynode[maxn];
int ans[maxn];
int n,q,uans;

bool cmp (const Querys &a,const Querys &b) {return a.a<b.a;}
bool cmptl (int a,int b) {return a<b;}
bool cmptr (int a,int b) {return a>b;}

void Init()
{
	scanf("%d%d",&n,&q);
	for (int i=1;i<=n;i++) scanf("%d",&h[i]);
	for (int i=1;i<=q;i++) scanf("%d%d",&qur[i].a,&qur[i].b),qur[i].id=i;
	sort(qur+1,qur+1+q,cmp);
	memcpy(ht,h,sizeof(h));
	for (int i=1;i<=q;i++) ht[n+i]=qur[i].b;
	sort(ht+1,ht+1+n+q);
	hs=unique(ht+1,ht+1+n+q)-(ht+1);
	for (int i=1;i<=hs;i++) M[ht[i]]=i;
	for (int i=1;i<=n;i++) h[i]=M[h[i]];
	for (int i=1;i<=q;i++) qur[i].b=M[qur[i].b];
	Tl.n=Tr.n=hs;
}

int Q[maxn],top;

void Get_F()
{
	memset(Q,0,sizeof(Q));top=0;
	for (int i=1;i<=n;i++)
	{
		int l=0,r=top,mid;
		while (l<r) if (Q[mid=((l+r+1)>>1)]<h[i]) l=mid;else r=mid-1;
		fl[i]=l+1;
		if (l==top) Q[++top]=h[i];
		else Q[l+1]=min(Q[l+1],h[i]);
	}
	uans=top;
	memset(Q,0,sizeof(Q));top=0;Q[0]=inf;
	for (int i=n;i>=1;i--)
	{
		int l=0,r=top,mid;
		while (l<r) if (Q[mid=((l+r+1)>>1)]>h[i]) l=mid;else r=mid-1;
		fr[i]=l+1;
		if (l==top) Q[++top]=h[i];
		else Q[l+1]=max(Q[l+1],h[i]);
	}
}

void Get_KeyNode()
{
	Tl.Clear();Tr.Clear();M.clear();
	for (int i=n;i>=1;i--) Tr.Insert(h[i],fr[i]);
	for (int i=1;i<=n;i++)
	{
		Tr.Delete(h[i],fr[i]);
		int kl=Tl.Query(1,h[i]-1),kr=Tr.Query(h[i]+1,hs);
		if (kl+kr+1==uans) keynode[i]=kl+1,M[kl+1]++;
			else keynode[i]=0;
		Tl.Insert(h[i],fl[i]);
	}
	for (int i=1;i<=n;i++) if (keynode[i]) keynode[i]=(M[keynode[i]]>1)?0:1;
}

void Solve()
{
	Tl.Clear();Tr.Clear();
	for (int i=n;i>=1;i--) Tr.Insert(h[i],fr[i]);
	for (int i=1,pos=0;i<=q;i++)
	{
		while (pos<qur[i].a)
		{
			Tl.Insert(h[pos],fl[pos]);
			++pos;
			Tr.Delete(h[pos],fr[pos]);
		}
		int res=Tl.Query(1,qur[i].b-1)+Tr.Query(qur[i].b+1,hs)+1;
		if (res<uans) ans[qur[i].id]=keynode[qur[i].a]==1?uans-1:uans;
		else ans[qur[i].id]=res;
	}
	for (int i=1;i<=q;i++) printf("%d\n",ans[i]);
}

int main()
{
	Init();
	Get_F();
	Get_KeyNode();
	Solve();
	return 0;
}

 

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter