codeforces1407D Saltos centrífugos discretos

https://codeforces.com/contest/1407/problem/D

No recibí la pregunta mdA, ¿verdad? Después de D, cuando vi el predictor cf, todavía obtuve el puntaje. Cuando me lavé los dientes, pensé en qué pregunta no usaría primero. Cuando vuelvo a ver esta pregunta, comprendo perfectamente que la constante de optimización diaria elimina a las personas.

Se puede encontrar que si queremos saltar de i a j, entonces supongamos que estamos actualmente en i, si a [i + 1]> a [i], entonces solo podemos transferir de acuerdo a una subsecuencia estrictamente descendente, de lo contrario es de acuerdo a un ascenso estricto Transferencia posterior,

Así que use una matriz de árbol para preprocesar el nxtup [i] más grande más cercano y el nxtd [i] más pequeño en el lado derecho de cada posición, y luego manténgase a la derecha para juzgar si se puede transferir, si no se ha actualizado O es mejor transferir que la transferencia actual.

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=3e5+10;

int n,m,cnt,tot,cas,ans;
int a[maxl],dp[maxl],num[maxl];
int b[maxl],nxtup[maxl],nxtd[maxl];
char s[maxl];

inline void upd(int i,int x)
{
	while(i<=tot)
	{
		b[i]=min(x,b[i]);
		i+=i&-i;
	}
}

inline int qry(int i)
{
	int ret=n+1;
	while(i)
	{
		ret=min(ret,b[i]);
		i-=i&-i;
	}
	return ret;
}

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),num[i]=a[i];
	sort(num+1,num+1+n);
	tot=unique(num+1,num+1+n)-num-1;
	for(int i=1;i<=n;i++)
		a[i]=lower_bound(num+1,num+1+tot,a[i])-num;
	for(int i=0;i<=tot;i++)
		b[i]=n+1;
	int c;
	for(int i=n;i>=1;i--)
	{
		c=a[i];
		nxtd[i]=qry(c-1);
		upd(c,i);
	}
	for(int i=0;i<=tot;i++)
		b[i]=n+1;
	for(int i=n;i>=1;i--)
	{
		c=tot-a[i]+1;
		nxtup[i]=qry(c-1);
		upd(c,i);
	}
}

inline void mainwork()
{
	dp[1]=0;int now,last;
	for(int i=2;i<=n;i++)
		dp[i]=n-1;
	for(int i=1;i<=n-1;i++)
	{
		dp[i+1]=min(dp[i+1],dp[i]+1);
		if(a[i+1]>a[i])
		{
			now=i+1;
			while(nxtd[now]<=n)
			{
				last=now;now=nxtd[now];
				if(dp[now]<=dp[i]+1 || a[last]<=a[i])
					break;
				dp[now]=min(dp[now],dp[i]+1);
			}
		}
		if(a[i+1]<a[i])
		{
			now=i+1;
			while(nxtup[now]<=n)
			{
				last=now;now=nxtup[now];
				if(dp[now]<=dp[i]+1 || a[last]>=a[i])
					break;
				dp[now]=min(dp[now],dp[i]+1);
			}
		}
	}
}

inline void print()
{
	printf("%d\n",dp[n]);
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/liufengwei1/article/details/108480967
Recomendado
Clasificación