Entrenamiento del algoritmo de Blue Bridge Cup la calculadora de Beaver fusionar clasificación java versión de 100 puntos

Descripción del problema

  El astuto castor de Universal Dictionary nos sorprendió una vez. Desarrolló una nueva calculadora, a la que llamó "Beaver's Calculator 1.0". Es muy especial y está previsto que se utilice en diversos problemas científicos.
  Para probarlo, el castor inteligente invitó a n científicos, numerados del 1 al n. El i-ésimo científico trajo k i problemas de cálculo a esta calculadora  . Los problemas planteados por el i-ésimo científico se numeran del 1 an, y deben calcularse uno a uno según el número, porque el cálculo de cada problema debe basarse en el resultado del cálculo del problema anterior.
  Cada pregunta es cada profesor con un número de  A i ,  J   para describir, i (1≤i≤n) es el número de científicos, J (1≤j≤  k i  ) es el número de preguntas,  A i ,  J   representa El número de unidades de recursos necesarias para resolver este problema.
  Esta calculadora es muy extraordinaria. Resuelve los problemas uno por uno. Después de que se resuelve un problema y antes de calcular el siguiente, la calculadora asigna o libera recursos.
  La operación más cara de la calculadora es liberar recursos, y la liberación es mucho más lenta que la asignación. Entonces, para la calculadora, es muy importante que cada pregunta siguiente requiera no menos que la anterior.
  Brindarle información relevante sobre las preguntas dadas por estos científicos. Debe organizar estas preguntas en un orden para que haya la menor cantidad posible de "pares incorrectos".
  El llamado "par malo" significa que en dos problemas adyacentes, el último requiere menos recursos que el anterior. No olvide, para los problemas dados por el mismo científico, el orden relativo de cálculo debe ser fijo.

Formato de entrada

  La primera línea contiene un número entero n, que representa el número de científicos. Cada una de las n líneas siguientes tiene 5 números enteros, k ia i , 1,  x iy im i  (0 ≤  a i , 1 <  m i  ≤ 109, 1 ≤  x i ,  y i  ≤ 109) , Representar respectivamente el número de preguntas del i-ésimo científico, el número de unidades de recursos requeridas para la primera pregunta y 3  parámetros utilizados para calcular  a i ,  j . una yo ,  j  = ( una yo ,  j  -1 *  x yo  +  y yo ) mod m yo.

Formato de salida

  La primera línea genera un número entero, que indica el menor número de "pares defectuosos" en el orden óptimo.
  Si el número total de problemas no supera los 200.000, la siguiente  línea de salida  indica el orden óptimo para resolver los problemas. Dos enteros separados por espacios en cada línea representan el número de unidades de recursos necesarias para este problema y el número del científico que proporcionó este problema.

Entrada de muestra

2
2 1 1 1 10
2 3 1 1 10

Salida de muestra

0
1 1
2 1
3 2
4 2

Tamaño de datos y convención

  20% de los datos  n  = 2, 1 ≤  k i  ≤ 2000;
  otro 30% de los datos  n  = 2, 1 ≤  k i  ≤ 200000; el
  50% restante de los datos 1 ≤  n  ≤ 5000, 1 ≤  k i  ≤ 5000.

Análisis: Para el problema de cada científico: 1. Combine cada grupo de problemas antes de encontrar un par incorrecto y cada grupo de problemas antes de que todos los científicos encuentren un par incorrecto (orden ascendente), fusionarlos y ordenarlos (clasificación estable) El método no afecta el orden de la matriz) 02. Repita el primer paso hasta que se resuelvan los problemas del científico.

Hoy estoy un poco cansado, pongamos el código. Pero fueron solo 70 puntos, no sé por qué no, así que lo comprobaré mañana. (El código correcto está a continuación).

package March;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Question11 {
//Beaver's Calculator  

	final static int maxn=5100;
	static class t{
		int pos,count;//pos:当前的位置,count:某一个科学家的问题数
		long  p[]=new long [maxn+5];//科学家对应问题的资源数 从一开始
	}
	static t q[]=new t[maxn+5];//保存每个科学家的问题情况
	
	static class s{//安排的对应情况
		int id;//对应的科学家
		long  key;//需要的资源
	}
	static s R[]=new s[40*maxn+5];//安排
	static s R1[]=new s[40*maxn+5];
	
	static void init()//初始化
	{
		for(int i=0;i<maxn+5;i++)
			q[i]=new t();
		
		for(int i=0;i<40*maxn+5;i++)
		{
			R[i]=new s();
			R1[i]=new s();
		}	
	}
	
	static void Merge(int s,int m,int t)
	{
		int i,j,k;
		i=s;//R1第一个序列的始点
		j=m+1;//R1第二个序列的始点
		k=s;//R的始点 
		while(i<=m&&j<=t)
		{
			if(R1[i].key<R1[j].key)//从小到大
				R[k++]=R1[i++];
			else
				R[k++]=R1[j++];
		}
		while(i<=m) R[k++]=R1[i++];//如果R1第二个序列先排完
		while(j<=t) R[k++]=R1[j++];//如果R1第一个序列先排完
		
		for(i=s;i<k;i++)
			R1[i]=R[i];//将拍好序列的元素再赋值给R1
		
	}
	
	static void Msort(int s,int t)//二分法归并
	{
		if(s<t)
		{
			int m=(s+t)/2;
			Msort(s,m);
			Msort(m+1,t);
			Merge(s,m,t);
		}
	}
	
	public static void main(String[] args) throws IOException {
		int n,k,r,x,y,m;
		int length=0;
		int ans=-1;
		int start=0,end=0;
		
		BufferedReader bfr=new BufferedReader(new InputStreamReader(System.in));//加快输入
		String str=bfr.readLine();
		String S[]=str.split(" ");
		n=Integer.parseInt(S[0]);
		
		init();
		
		for(int i=1;i<=n;i++)
		{
			str=bfr.readLine();
			S=str.split(" ");
			k=Integer.parseInt(S[0]);
			r=Integer.parseInt(S[1]);
			x=Integer.parseInt(S[2]);
			y=Integer.parseInt(S[3]);
			m=Integer.parseInt(S[4]);
			int sum=0;
			length+=k;
			q[i].pos=1;//现在的位置
			q[i].count=k;//科学家i的问题总数
			q[i].p[1]=r;//第一个问题所需资源数
			for(int j=2;j<=k;j++)
			{
				q[i].p[j]=(x*q[i].p[j-1]+y)%m;
				if(q[i].p[j]<q[i].p[j-1])
					sum++;
			}
			ans=Math.max(ans, sum);
			//我们所需要求的最优顺序下最少的“坏对”个数,就是所有科学家所提出的问题的序列中的最多“坏对”的个数,即为所求。
		}
		System.out.println(ans);
		
		if(length<=200000)//依题意
		{
			while(end<length)//从0开始
			{
				for(int i=1;i<=n;i++)
				{
					int j;
					for( j=q[i].pos;j<=q[i].count;j++)
					{
						if(j!=q[i].pos&&q[i].p[j]<q[i].p[j-1])//发现坏对
						{
							q[i].pos=j;
							break;//跳出循环 破坏之  求的都是升序段
						}
						R1[end].id=i;
						R1[end++].key=q[i].p[j];
					}
					if(j>q[i].count)
						q[i].pos=j;//已完,科学家i的问题不在参与循环
				}
				Msort(start,end-1);//对所有科学家的升序段进行排序不会改变某一个科学家问题排列的相对位置。随便举个例子就OK啦,
				//end-1是因为 前面的是end++ 后自增,所以结束时,其大小要比数组最后一个有意义的值的序列值要大1
				start=end;//同理 ,开始下一段
			}
			for(int i=0;i<length;i++)
				System.out.println(R1[i].key+" "+R1[i].id);
		}
		
	}

}

Detalles de la evaluación:

registro detallado
Número de punto de evaluación Resultados de evaluación Puntuación uso de CPU Uso de memoria Descargar datos de evaluación
1 correcto 5,00 640ms 244,3 MB Entrada y  salida
2 correcto 5,00 421 ms 244,4 MB Privilegios VIP
3 correcto 5,00 515ms 250,6 MB Privilegios VIP
4 correcto 5,00 609ms 247,2 MB Privilegios VIP
5 Error de ejecución 0,00 515ms 244,7 MB Privilegios VIP
6 Error de ejecución 0,00 359ms 244,9 MB Privilegios VIP
7 Error de ejecución 0,00 531ms 244,5 MB Privilegios VIP
8 Error de ejecución 0,00 718 ms 244,7 MB Privilegios VIP
9 Error de ejecución 0,00 796ms 244,6 MB Privilegios VIP
10 Error de ejecución 0,00 406ms 244,5 MB Privilegios VIP
11 correcto 5,00 812ms 248,6 MB Privilegios VIP
12 correcto 5,00 671 ms 248,5 MB Privilegios VIP
13 correcto 5,00 890ms 248,8 MB Privilegios VIP
14 correcto 5,00 843 ms 248,8 MB Privilegios VIP
15 correcto 5,00 843 ms 248,3 MB Privilegios VIP
dieciséis correcto 5,00 593ms 248,7 MB Privilegios VIP
17 correcto 5,00 828 ms 248,7 MB Privilegios VIP
18 correcto 5,00 859ms 248,8 MB Privilegios VIP
19 correcto 5,00 796ms 248,7 MB Privilegios VIP
20 correcto 5,00 859ms 248,7 MB Privilegios VIP

Después de pensarlo durante varios días, no sabía qué pasaba. Hasta el 11 de marzo, de repente descubrí que el 30% de los errores operativos no eran los mismos que de costumbre. Luego debe haber otras razones. Baidu descubrió que debería ser La matriz está fuera de los límites, por lo que varios cambios, errores ~~~, finalmente mire el tamaño de los datos

Tamaño de datos y convención

  20% de los datos  n  = 2, 1 ≤  k i  ≤ 2000;
  otro 30% de los datos  n  = 2, 1 ≤  k i  ≤ 200000; el
  50% restante de los datos 1 ≤  n  ≤ 5000, 1 ≤  k i  ≤ 5000.

En segundo lugar, ki puede ser de hasta 200.000, por lo que descubrí que t estaba mal porque la matriz p en t se abrió a 5005, lo cual no está mal.

Después de eso, cambié el tamaño de la matriz p a 200005. Pensé que habría pasado, pero la memoria está invadida, I r, y mire más de cerca, eh, n = 2, jejeje, discusión de caso especial,

if (n == 2) {} else {}, una vez enviado, ac, jajaja,

el código se muestra a continuación:



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//100points

public class Main {
//Beaver's Calculator  

	final static int maxn=5000;
	static class t{
		int pos,count;//pos:当前的位置,count:某一个科学家的问题数
		long  p[]=new long [maxn+5];//科学家对应问题的资源数 从一开始
	}
	static class T2{
		int pos,count;//pos:当前的位置,count:某一个科学家的问题数
		long  p[]=new long [200005];//科学家对应问题的资源数 从一开始
	}
	static t q[];//保存每个科学家的问题情况
	static T2 Q[];//n=2时  p[i] i=200005很大 会炸内存,必须先搞出来
	
	static class s{//安排的对应情况
		int id;//对应的科学家
		long  key;//需要的资源
	}
	static s R[]=new s[200005];//安排
	static s R1[]=new s[200005];
	
	static void init(int n)//初始化
	{
		if(n==2)//分类讨论
		{
			Q=new T2[3];	
			for(int i=1;i<=n;i++)//从1开始计数
				Q[i]=new T2();
		}
		else
		{
			q=new t[n+1];	
			for(int i=1;i<=n;i++)
				q[i]=new t();
		}
		
		for(int i=0;i<200005;i++)
		{
			R[i]=new s();
			R1[i]=new s();
		}	
	}
	
	static void Merge(int s,int m,int t)
	{
		int i,j,k;
		i=s;//R1第一个序列的始点
		j=m+1;//R1第二个序列的始点
		k=s;//R的始点 
		while(i<=m&&j<=t)
		{
			if(R1[i].key<R1[j].key)//从小到大
				R[k++]=R1[i++];
			else
				R[k++]=R1[j++];
		}
		while(i<=m) R[k++]=R1[i++];//如果R1第二个序列先排完
		while(j<=t) R[k++]=R1[j++];//如果R1第一个序列先排完
		
		for(i=s;i<k;i++)
			R1[i]=R[i];//将拍好序列的元素再赋值给R1
		
	}
	
	static void Msort(int s,int t)//二分法归并
	{
		if(s<t)
		{
			int m=(s+t)/2;
			Msort(s,m);
			Msort(m+1,t);
			Merge(s,m,t);
		}
	}
	
	public static void main(String[] args) throws IOException {
		int n,r,k,x,y,m;
		
		int length=0;
		int ans=-1;
		int start=0,end=0;
		
		BufferedReader bfr=new BufferedReader(new InputStreamReader(System.in));
//加快输入
		String str=bfr.readLine();
		String S[]=str.split(" ");
		n=Integer.parseInt(S[0]);
		
		init(n);
		
		for(int i=1;i<=n;i++)
		{
			str=bfr.readLine();
			S=str.split(" ");
			k=Integer.parseInt(S[0]);
			r=Integer.parseInt(S[1]);
			x=Integer.parseInt(S[2]);
			y=Integer.parseInt(S[3]);
			m=Integer.parseInt(S[4]);
			
			int sum=0;
			length+=k;
			if(n==2)
			{
				Q[i].pos=1;//现在的位置
				Q[i].count=k;//科学家i的问题总数
				Q[i].p[1]=r;//第一个问题所需资源数
				for(int j=2;j<=k;j++)
				{
					Q[i].p[j]=(Q[i].p[j-1]*x+y)%m;
					if(Q[i].p[j]<Q[i].p[j-1])
						sum++;
				}
			}
			else
			{
				q[i].pos=1;//现在的位置
				q[i].count=k;//科学家i的问题总数
				q[i].p[1]=r;//第一个问题所需资源数
				for(int j=2;j<=k;j++)
				{
					q[i].p[j]=(q[i].p[j-1]*x+y)%m;
					if(q[i].p[j]<q[i].p[j-1])
						sum++;
				}
			}
			
			ans=Math.max(ans, sum);
//我们所需要求的最优顺序下最少的“坏对”个数,就是所有科学家所提出的问题的序列中的最多“坏对”的个
//数,即为所求。
		}
		System.out.println(ans);
		
		if(length<=200000)//依题意
		{
			while(end<length)//从0开始
			{
				if(n==2)
				{
					for(int i=1;i<=n;i++)
					{
						int j;
						for( j=Q[i].pos;j<=Q[i].count;j++)
						{
							if(j!=Q[i].pos&&Q[i].p[j]<Q[i].p[j-1])//发现坏对
							{
								Q[i].pos=j;
								break;//跳出循环 破坏之  求的都是升序段
							}
							R1[end].id=i;
							R1[end++].key=Q[i].p[j];
						}
						if(j>Q[i].count)
							Q[i].pos=j;//已完,科学家i的问题不在参与循环
					}
				}
				else
				{
					for(int i=1;i<=n;i++)
					{
						int j;
						for( j=q[i].pos;j<=q[i].count;j++)
						{
							if(j!=q[i].pos&&q[i].p[j]<q[i].p[j-1])//发现坏对
							{
								q[i].pos=j;
								break;//跳出循环 破坏之  求的都是升序段
							}
							R1[end].id=i;
							R1[end++].key=q[i].p[j];
						}
						if(j>q[i].count)
							q[i].pos=j;//已完,科学家i的问题不在参与循环
					}
				}
			
				Msort(start,end-1);
//对所有科学家的升序段进行排序不会改变某一个科学家问题排列的相对位置。随便举个例子就OK啦,
//end-1是因为 前面的是end++ 后自增,所以结束时,其大小要比数组最后一个有意义的值的序列值要大1
				start=end;//同理 ,开始下一段
			}
			for(int i=0;i<length;i++)
				System.out.println(R1[i].key+" "+R1[i].id);
		}
		
	}

}

Detalles de la evaluación:

registro detallado
Número de punto de evaluación Resultados de evaluación Puntuación uso de CPU Uso de memoria Descargar datos de evaluación
1 correcto 5,00 265 ms 33.11 MB Entrada y  salida
2 correcto 5,00 171 ms 33,13 MB Privilegios VIP
3 correcto 5,00 484 ms 42,58 MB Privilegios VIP
4 correcto 5,00 390 ms 41,54 MB Privilegios VIP
5 correcto 5,00 218ms 33,98 MB Privilegios VIP
6 correcto 5,00 156 ms 33,98 MB Privilegios VIP
7 correcto 5,00 250 ms 33,86 MB Privilegios VIP
8 correcto 5,00 218ms 34,06 MB Privilegios VIP
9 correcto 5,00 203 ms 33,98 MB Privilegios VIP
10 correcto 5,00 234ms 33,92 MB Privilegios VIP
11 correcto 5,00 750 ms 236,1 MB Privilegios VIP
12 correcto 5,00 921 ms 235,9 MB Privilegios VIP
13 correcto 5,00 765ms 235,6 MB Privilegios VIP
14 correcto 5,00 687ms 236,1 MB Privilegios VIP
15 correcto 5,00 812ms 235,6 MB Privilegios VIP
dieciséis correcto 5,00 703ms 235,9 MB Privilegios VIP
17 correcto 5,00 781ms 235,7 MB Privilegios VIP
18 correcto 5,00 656ms 235,6 MB Privilegios VIP
19 correcto 5,00 843 ms 235,8 MB Privilegios VIP
20 correcto 5,00 796ms 236,0 MB Privilegios VIP

para resumir:

1. De hecho, esta pregunta no es muy difícil, es decir, algunos datos tendrán problemas. La próxima vez que corrijas el error, primero debes identificar el tipo de error y luego prescribir el medicamento correcto. No cometas errores, de lo contrario será una pérdida de tiempo. (El error de ejecución de la Copa Lanqiao es generalmente el grupo de índice fuera de los límites)

2. Cuando se encuentre con un problema, analícelo con calma y sea firme.

3. Después de unos días de enredo, ¡se siente genial resolver un problema! ! !

 

Supongo que te gusta

Origin blog.csdn.net/Look_star/article/details/88262410
Recomendado
Clasificación