El entrenamiento de rehabilitación equivocado-CF1329B & C: Secuencias del montón

CF1329B Dreamoon le gusta secuencias

Descripción del título

Una secuencia es elegible si y solo si la secuencia no está vacía y aumenta monotónicamente y el prefijo XOR y aumenta monotónicamente.
Dado \ (d, m \) ( \ (d, m \ leq 10 ^ 9 \) ), pregunte a todos los números en la secuencia que cada número es un entero positivo que no exceda \ (d \) . ¿Cuál es el número de módulo \ (m \) ?

Solución

Suponga que la longitud de una secuencia legal es \ (n \) , la secuencia es \ (a_1, a_2, ..., a_n \) , y la suma del prefijo es \ (b_1, b_2, ..., b_n \) .
Si desea aumentar \ (\ {b_n \} \) , debe tener \ (\ forall i, b_i <b_ {i + 1} \) .
\ (b_i <b_ {i + 1} \) Hay dos casos: 1. El bit binario más alto de \ (b_ {i + 1} \) es más alto que \ (b_i \) ; 2. El bit binario más alto de ambos Lo mismo, y después de restar el bit más alto de ambos, \ (b_ {i + 1} \) es más grande.
Considere el segundo caso, tanto encontrado que si el bit más alto de la misma, por el \ (a_ {i + 1} = b_i \ xor espacio \ b_ espacio {i + 1} \) disponible \ (a_ {i + 1} \ ) Tiene el bit más alto más bajo que \ (b_i \) , y el bit más alto de al menos uno de \ (a_1, ..., a_i \) es lo mismo que \ (b_i \) , que es lo mismo que \ (\ {a_n \} \) Las condiciones para el aumento individual no coinciden.
Entonces no hay una segunda situación. En otras palabras, \ (\ {b_n \} \)El bit binario más alto de cada número es más alto que el número anterior.
Se puede concluir que el dígito binario más alto de cada número en \ (\ {a_n \} \) es más alto que el número anterior.
El \ (1,2, ..., d \ ) números clasificado de acuerdo con los bits más altos. Puedes elegir uno o no en cada categoría.

Código

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
void write(int x)
{
	char ch[20];int f=0;
	if(!x){putchar('0'),putchar('\n');return;}
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10+'0',x/=10;
	while(f)putchar(ch[f--]);
	putchar('\n');
}
int t,d,m,ans;
int mo(int x){if(x>=m)return x-m;if(x<0)return x+m;return x;}
int main()
{
	t=read();
	while(t--)
	{
		d=read(),m=read();ans=1;
		LL now=1,nxt=1;
		while(1)
		{
			if(nxt>=d){ans=(LL)ans*(d-now+2)%m;break;}
			ans=(LL)ans*(nxt-now+2)%m,now=nxt+1;nxt=(now<<1)-1;
		}
		ans=mo(ans-1);
		write(ans);
	}
	return (~(0-0)+1);
}

CF1329C A Brasil le gusta el montón

Descripción del título

Hay un árbol binario completo algo ponderado con una altura de \ (h \) , que satisface la naturaleza de los grandes montones de raíces.
Elimine un punto que no sea una hoja. El hijo con un peso mayor se moverá a la posición del punto y luego repetirá el proceso en la posición original del hijo.
Para eliminar algunos puntos, conviértalo en un árbol binario completo con una altura de \ (g \) , y el peso de los puntos restantes es lo más pequeño posible. Pregunte el peso mínimo de puntos y qué puntos eliminar.
Todos los puntos tienen pesos de puntos diferentes, \ (g \ leq h \ leq 20 \) .

Solución

En primer lugar, se descubre que los pesos de puntos de las partes restantes no tienen nada que ver con el orden de eliminación de puntos, porque los pesos de puntos de cada punto se convertirán en el valor máximo del árbol atómico después de la eliminación.
Considere un método de construcción codicioso: construya de abajo hacia arriba, de modo que el nuevo peso de punto de cada punto sea el peso de punto más pequeño posible en el árbol atómico que sea mayor que los nuevos pesos de punto de los hijos alrededor del punto.
La selección del peso del punto lo más pequeño posible no hará que el límite inferior del antepasado del punto sea más grande.
Es posible mantener una matriz de ponderación de puntos de subárbol en orden de tamaño en cada punto. Una matriz de puntos puede fusionarse mediante la matriz de hijos izquierdos y derechos en un método de clasificación similar. Complejidad de tiempo \ (\ Theta (2 ^ h \ times h) \) .
Si usa todos los hijos que atraviesan el punto cada vez para encontrar su peso en puntos, la complejidad del tiempo también es \ (\ Theta (2 ^ h \ times h) \) , pero la constante recursiva es ligeramente mayor.

Hay otro enfoque codicioso completamente intuitivo para este problema: elimine el valor en la raíz actual hasta que la distancia desde la hoja más cercana a la raíz sea \ (g \) , y luego procese los subárboles izquierdo y derecho de forma recursiva.
Debido a que el valor máximo está en la parte superior del montón, y cuando un punto y todos sus antepasados ​​no se pueden eliminar, no hay ningún efecto entre sus subárboles izquierdo y derecho. La complejidad del tiempo también es \ (\ Theta (2 ^ h \ times h) \)

Código

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
using namespace std;
#define maxn ((1<<20)+7)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define ls (u<<1)
#define rs (u<<1|1)
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
void write(LL x)
{
	char ch[20];int f=0;
	if(!x){putchar('0'),putchar('\n');return;}
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10+'0',x/=10;
	while(f)putchar(ch[f--]);
	putchar('\n');
}
int t,n,h,g,a[maxn],yes[maxn],len,dfn[maxn],siz[maxn],val[maxn];
LL ans;
pii ar[maxn],tmp[maxn];
void merge(int u)
{
	int nl=dfn[ls],nr=dfn[rs],c=0;
	rep(i,1,siz[u])
	{
		int va=(nl>=dfn[ls]+siz[ls]?1e9:ar[nl].fi),
		vb=(nr>=dfn[rs]+siz[rs]?1e9:ar[nr].fi),
		vc=c?1e9:a[u];
		if(va<min(vb,vc)){tmp[i].fi=va,tmp[i].se=ar[nl].se,nl++;}
		else if(vb<min(va,vc)){tmp[i].fi=vb,tmp[i].se=ar[nr].se,nr++;}
		else tmp[i].fi=a[u],tmp[i].se=u,c++;
	}
	rep(i,1,siz[u])ar[dfn[u]+i-1]=tmp[i];
}
int getv(int u,int li)
{
	int L=dfn[u],R=dfn[u]+siz[u]-1;pii res;res.fi=1e9;
	while(L<=R)
	{
		int mid=(L+R>>1);
		if(ar[mid].fi>li)
		{
			if(res.fi>ar[mid].fi)res=ar[mid];
			R=mid-1;	
		}
		else L=mid+1;
	}
	yes[res.se]=1;
	return res.fi;
}
void work(int u,int d)
{
	if(d==g)
	{
		sort(ar+dfn[u],ar+dfn[u]+siz[u]);
		val[u]=ar[dfn[u]].fi,yes[ar[dfn[u]].se]=1,ans+=val[u];
		return;
	}
	work(ls,d+1),work(rs,d+1),merge(u);
	val[u]=getv(u,max(val[ls],val[rs])),ans+=val[u];
	return;
}
void build(int u,int d)
{
	dfn[u]=++len,ar[len].fi=a[u],ar[len].se=u,siz[u]=1;
	if(d==h){return;}
	build(ls,d+1),build(rs,d+1),siz[u]+=siz[ls]+siz[rs];
	return;
}
int main()
{
	t=read();
	while(t--)
	{
		h=read(),g=read(),n=(1<<h)-1;ans=len=0;
		rep(i,1,n)a[i]=read(),yes[i]=0;
		build(1,1);
		work(1,1);
		write(ans);
		dwn(i,n,1)if(!yes[i])printf("%d ",i);
		puts("");
	}
	return (~(0-0)+1);
}

Algunos pensamientos

No seas negro cuando cruces la línea de fuego: formar equipo con alguien que cruza la línea de fuego no puede mejorar el nivel, y formar equipo con alguien que no es tan fuerte no puede aumentar el puntaje.
Sin embargo, piratear con personas con un inglés fuerte puede mejorar tanto el nivel (refiriéndose a tener más tiempo para pensar antes de quedarse dormido en lugar de traducir) como mejorar el puntaje (refiriéndose a tener más tiempo para pensar en la pregunta, que es más fácil de calificar). :)

Supongo que te gusta

Origin www.cnblogs.com/xzyf/p/12664515.html
Recomendado
Clasificación