HDU6406 Taotao Picks Apples

题意:给你一个序列,n个点m个询问,问你如果把第p个数字变成q,第一个元素为开头,遇到大的必选的严格上升子序列的长度

考场上很久才A掉,太菜了QAQ,突然想起这种必取的之前在claris的多校中做过,倒着单调队列就能预处理出以每个元素开头,遇到大的必选的严格上升子序列的长度upnum[i],于是我们就想到了吧询问离线倒着处理,先预处理出原本应该在队列中的是哪些元素,然后我们看当前询问的最近的原队列中的元素是哪一个,然后考虑变成q后,是否最近的原序列中的元素会接着他,再去他后面找到最近的比他严格大的元素,这里我用了线段树维护,权值当下标,mini记录index的最小值,然后再+upnum[i]

还有很多做法,比如dls的队友是直接在线做的,就主席树一蛤,找到在他之后的最近的比他大的元素(我不太会写。。。)。还有直接把所有原序列中不被选的元素也开成vector,然后构成严格上升序列,每次在线就直接二分,我想了一蛤好像我那个线段树也可以倒着搞个单调队列,然后每次二分一蛤找到最近的比他大的元素,题解好像是ST表找,好像也行

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 100010
#define inf 2000000001

using namespace std;

namespace fastIO {
#define BUF_SIZE 100000
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline int rd(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror) return -1;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
return 1;
}
#undef BUF_SIZE
};
using namespace fastIO;

int n,m,cnt,inilen;
int a[maxl],upnum[maxl],ans[maxl],c[maxl<<1];
int inih[maxl],iniind[maxl];
struct node
{
	int l,r,mini;
}tree[maxl<<3];
struct number
{
	int num,id;bool isa;
}numm[maxl<<1];
struct que
{
	int p,q,id;
}b[maxl];
char s[20];

inline bool cmpnum(const number &x,const number &y)
{
	return x.num<y.num;
}

inline bool cmpque(const que &x,const que &y)
{
	return x.p>y.p;
}

inline void build(int k,int l,int r)
{
	tree[k].l=l;tree[k].r=r;tree[k].mini=inf;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}

inline void prework()
{
	rd(n);rd(m);cnt=0;
	for(register int i=1;i<=n;++i)
	{
		rd(a[i]);
		numm[++cnt].num=a[i];numm[cnt].id=i;numm[cnt].isa=true;
	}
	for(register int i=1;i<=m;++i)
	{
		rd(b[i].p);rd(b[i].q);b[i].id=i;
		numm[++cnt].num=b[i].q;numm[cnt].id=i;numm[cnt].isa=false;
	}
	sort(numm+1,numm+1+cnt,cmpnum);
	cnt=1;
	if(numm[1].isa)
		a[numm[1].id]=1;
	else
		b[numm[1].id].q=1;
	for(register int i=2;i<=n+m;++i)
	{
		if(numm[i].num!=numm[i-1].num)
			cnt++;
		if(numm[i].isa)
			a[numm[i].id]=cnt;
		else
			b[numm[i].id].q=cnt;
	}
	int len=0;int head=1,tail=0;
	for(register int i=n;i>=1;--i)
	{
		while(tail>=head && a[i]>=c[tail])
			tail--,len--;
		len++;c[++tail]=a[i];upnum[i]=len;
	}
	sort(b+1,b+1+m,cmpque);
	inilen=1;
	inih[1]=a[1];iniind[1]=1;
	for(register int i=2;i<=n;++i)
	if(a[i]>inih[inilen])
		inih[++inilen]=a[i],iniind[inilen]=i;
	build(1,1,cnt);
}

inline int min(int a,int b){return a<b?a:b;}

inline void add(int k,int l,int x)
{
	if(tree[k].l==tree[k].r)
	{
		tree[k].mini=min(tree[k].mini,x);
		return;
	}
	int mid=(tree[k].l+tree[k].r)>>1;
	if(l<=mid)
		add(k<<1,l,x);
	else
		add(k<<1|1,l,x);
	tree[k].mini=min(tree[k<<1].mini,tree[k<<1|1].mini);
}

inline int query(int k,int l,int r)
{
	if(l>r)
		return inf;
	if(tree[k].l==l && tree[k].r==r)
		return tree[k].mini;
	int mid=(tree[k].l+tree[k].r)>>1;
	if(r<=mid)
		return query(k<<1,l,r);
	else
	if(l>mid)
		return query(k<<1|1,l,r);
	else
		return min(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
}

inline void mainwork()
{
	int len=inilen,l=n,st,idx;
	inih[len+1]=-1;
	for(register int i=1;i<=m;++i)
	{
		while(b[i].p<=iniind[len])
			len--;
		while(l>=b[i].p+1)
		{
			add(1,a[l],l);
			l--;
		}
		if(b[i].q>inih[len])
		{
			idx=query(1,b[i].q+1,cnt);
			if(idx==inf)
				ans[b[i].id]=len+1;
			else
				ans[b[i].id]=len+1+upnum[idx];
		}
		else
		{
			idx=query(1,inih[len]+1,cnt);
			if(idx==inf)
				ans[b[i].id]=len;
			else
				ans[b[i].id]=len+upnum[idx];
		}
	}
}

inline void pf(int x)
{
	int top=0;
	while(x)
	{
		s[++top]=(x%10)+'0';
		x=x/10;
	}
	for(register int i=top;i>=1;i--)
		putchar(s[i]);
}

inline void print()
{
	for(register int i=1;i<=m;i++)
	{
		pf(ans[i]);
		putchar('\n');
	}
}

int main()
{
	int t;
//	freopen("1010.in","r",stdin);
//	freopen("1010.out","w",stdout);
	rd(t);
	for(register int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/81736234