Luchadores Japoneses

No se que esta mal aaa

#include <iostream>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <stdlib.h>
#include <sstream>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <string>
#include <vector>
using namespace std;
int main () {
		int l;
		int p;
		int cont=0;
		cin>>l;
		int s[l][2];
		for (int i = 0; i < l; i++) {
			for (int b = 0; b < 2; b++) {
				cin>>p;
				s[i][b]=p;
			}
		}
		for(int w = 0; w < l; w++){
			cont =0;
			for(int o = 0; o < l; o++){
			if((s[w][0]>s[o][0] and s[w][1]>=s[o][1]) or (s[w][1]>s[o][1] and s[w][0]>=s[o][0]))
			cont++;
			}
			cout<<cont<<endl;
			}
}

alguien sabe?

1 me gusta

Hola, ¿podrías contarnos un poquito más? ¿Qué tipo de error recibes del juez online (Respuesta incorrecta, Tiempo Límite Excedido, Límite de memoria excedido)?

De todas formas (si nadie responde antes) a la tarde lo miro en detalle, pero la respuesta del juez hace que tome menos tiempo ver lo que está pasando.

1 me gusta

Hola gracias por responder me aparece 0/100

2 Me gusta

Hola, por lo que leo del código creo que tu problema es que debe pasarse de tiempo, es decir, como dijo @Guty, dar Tiempo Límite Excedido.
Esto se debe a que el problema, siendo L la cantidad de luchadores, 1 \leq L \leq 100.000 . Vos haces dos fors anidados, así recorriendo por cada luchador, el resto de los luchadores, quedando una complejidad de \mathcal{O}(n^2), es decir, recorres cada luchador L veces, y tarda mucho tiempo ejecutando L^2 operaciones.

Para poder comprobar mejor el problema de tu código, podés hacer click en el ID asignado al submission, y ahí muestra por cada uno de los casos de prueba, si el resultado es correcto, incorrecto, se pasa en memoria o tiempo.

Pensándolo, si ese código que mandaste es el mismo que subiste al juez, te falta también ingresar la información y escribirla al archivo correspondiente. Como dice en el problema, uno tiene que recibir información desde el archivo \color {white}\text{sumo.in} y devolver el resultado por el archivo \color {white} \text{sumo.out}. Para eso, a mi me gusta al menos, poner al principio del main, como sería en este caso freopen("sumo.in","r",stdin); y freopen("sumo.out","w",stdout);, así siendo: el primer parámetro el nombre del archivo, el segundo r si es la operación \text{read} (leer de archivo) o w si la operación es \text{write} (escribir al archivo), y el último parámetro, sería a donde/de donde viene la información de uno lee\escribe. En este caso \text{stdin} sería la entrada estándar, \text{stdout} la salida estándar. Seguro cuando hacés eso, si bien no da todo el puntaje, puede dar bien en parte de los casos con cantidad de luchadores más bajas.

2 Me gusta

Concuerdo con todo lo que dijo @ariloc en el post anterior.

Cualquier cosa igual no dudes en consultar.

Para enviar este problema al juez esto es clave. Aunque esté perfecto, si no se respeta el formato de entrada y de salida, todo envío va a sacar 0 puntos. Eso cambia de problema en problema (en general en los problemas más viejos se pide escribir y leer de un archivo). Es muy importante leer y comprender el enunciado del problema.

1 me gusta

¡Buenas! Adjunto mi inconveniente con este problema. El error que me tira el juez es de respuesta incorrecta y no se que hice mal.

Mi idea

Se tiene a todos los luchadores ordenados por peso (y si empatan entonces por altura). Luego se crea un Segment Tree que en cada segmento (i, j) almacene la cantidad de luchadores que tengan una altura entre i y j - 1 que empiece vacío. Entonces por cada luchador se haría una consulta en el Segment Tree con los parámetros (0, h) en caso de que el luchador anterior tenga el mismo peso o (0, h + 1) en caso contrario. Después de esto se actualiza el Segment Tree sumándole 1 al nodo correspondiente a la altura del luchador actual.

No se qué es lo que falla o si me estoy olvidando de algún caso base.

Código
#include<bits/stdc++.h>
#define forn(i, n) for(int i = 0; i < n; i++)
#define fori(i, a, n) for(int i = a; i < n; i++)
#define forrt(i, n) for(int i = n; i >= 0; i--);
using namespace std;
const int MAXN = 100010, MAXPH =  11000010;
struct segtree{
	int n, *st;
	segtree(int t){
		n = 2 * pow(2, ceil(log2(t))) - 1;
		st = new int[n];
		forn(i, n) st[i] = 0;
	}
	int query(int qi, int qd, int si, int sd, int index){
		if(qi >= sd || qd <= si) return 0;
		if(si >= qi && sd <= qd) return st[index];
		int m = (si + sd) / 2;
		return query(qi, qd, si, m, index * 2 + 1) + query(qi, qd, m, sd, index * 2 + 2);
	}
	int query(int qi, int qd){
		return query(qi, qd, 0, n / 2 + 1, 0);
	}
	int update(int index){
		index += (n / 2);
		st[index]++;
		while(index > 0){
			index = (index - 1) / 2;
			st[index] = st[index * 2 + 1] + st[index * 2 + 2];
		}
	}
};
struct sumo{
	int p, h, id;
	bool operator < (const sumo &b)const{
		if(p == b.p) return h < b.h;
		return p < b.p;
	}
};
int main(){
	ifstream cin("sumo.in");
	ofstream cout("sumo.out");
	int n, res[MAXN];
	sumo sumos[MAXN];
	segtree st(MAXPH);
	cin>>n;
	forn(i, n){
		cin>>sumos[i].p>>sumos[i].h;
		sumos[i].id = i;
	}
	sort(sumos, sumos + n);
	res[sumos[0].id] = 0;
	st.update(sumos[0].h);
	fori(i, 1, n){
		if(sumos[i].p == sumos[i - 1].p) res[sumos[i].id] = st.query(0, sumos[i].h);
		else res[sumos[i].id] = st.query(0, sumos[i].h + 1);
		st.update(sumos[i].h);
	}
	forn(i, n) cout<<res[i]<<"\n";
	return 0;
}

Muchas gracias :blush:

2 Me gusta

Hola! Yo en mi caso lo resolví con Fenwick, está en mi lista de pendientes ver un poco Segment Tree, jeje. Pero igual me parecía raro que dividieras por el caso de luchadores de misma y distinta altura. Entonces cambié un par de cosas de tu código y entró :grinning: (claramente aclaré que no era mío en un comentario).

Nomás saqué la condición y dejé la línea res[sumos[i].id] = st.query(0, sumos[i].h + 1);. Y por supuesto, como ya no tenés que consultar al anterior por la condición, no hace falta separar el caso 0 y empezar el for en 1, por lo que directamente lo cambié en un forn(i, n).

Lo único que se me ocurre que podía estar pasando, es que la forma en que armaste el Segment Tree (repito que si bien entiendo cómo funcionan, no lo he aplicado aún en código), al devolver los valores para cierto luchador necesitás consultar por sumos[i].h + 1, y con la condición te podías estar salteando luchadores que uno superaba por tener igual peso y altura.

EDIT: El enunciado dice que no deberían haber luchadores de ambas medidas. Por lo tanto no sé entonces qué puede ser (abajo puse un comentario aparte).

Así funcionó:

Tu código 100/100
#define forn(i, n) for(int i = 0; i < n; i++)
#define fori(i, a, n) for(int i = a; i < n; i++)
#define forrt(i, n) for(int i = n; i >= 0; i--);
using namespace std;
const int MAXN = 100010, MAXPH =  11000010;

/*
ESTE NO ES MI CÓDIGO. ESTOY PROBANDO EL CÓDIGO DEL USER JoacruYT
PARA EL POST http://foro.oia.unsam.edu.ar/t/luchadores-japoneses/521/6
*/

struct segtree{
	int n, *st;
	segtree(int t){
		n = 2 * pow(2, ceil(log2(t))) - 1;
		st = new int[n];
		forn(i, n) st[i] = 0;
	}
	int query(int qi, int qd, int si, int sd, int index){
		if(qi >= sd || qd <= si) return 0;
		if(si >= qi && sd <= qd) return st[index];
		int m = (si + sd) / 2;
		return query(qi, qd, si, m, index * 2 + 1) + query(qi, qd, m, sd, index * 2 + 2);
	}
	int query(int qi, int qd){
		return query(qi, qd, 0, n / 2 + 1, 0);
	}
	int update(int index){
		index += (n / 2);
		st[index]++;
		while(index > 0){
			index = (index - 1) / 2;
			st[index] = st[index * 2 + 1] + st[index * 2 + 2];
		}
	}
};
struct sumo{
	int p, h, id;
	bool operator < (const sumo &b)const{
		if(p == b.p) return h < b.h;
		return p < b.p;
	}
};
int main(){
	ifstream cin("sumo.in");
	ofstream cout("sumo.out");
	int n, res[MAXN];
	sumo sumos[MAXN];
	segtree st(MAXPH);
	cin>>n;
	forn(i, n){
		cin>>sumos[i].p>>sumos[i].h;
		sumos[i].id = i;
	}
	sort(sumos, sumos + n);
	//res[sumos[0].id] = 0;
	//st.update(sumos[0].h);
	forn(i, n){
		res[sumos[i].id] = st.query(0, sumos[i].h + 1);
		st.update(sumos[i].h);
	}
	forn(i, n) cout<<res[i]<<endl;
	return 0;
}
2 Me gusta

Había separado el caso ese porque en caso de que tengan el mismo peso la altura tenía que ser si o si menor. En cambio si el peso era menor, la altura podía ser igual o menor para dominarlo. Me sigue pareciendo raro que si entre sin tener en cuenta esa posibilidad.
Muchas gracias por tu ayuda :blush:

Efectivamente. Probé el código corregido con un caso en el que hay dos luchadores con el mismo peso y altura y el que queda al final queda como que domina al otro.
Entrada de ejemplo:

2
10 10
10 10

Salida de ese ejemplo:

0
1

Cuando la salida debería ser:

0
0

Ya que ninguno puede dominar al otro.
@santo, ¿habrá algún fallo en los casos de prueba?

Igual es aún más raro porque el enunciado además dice Sabiendo que no hay luchadores que coinciden en ambas medidas (…). Por eso yo no me preocupé de ese caso. Así que no sé si tu código estaba fallando en algo más o si los casos de prueba al final si tenían repetidos (igual recién lo leo, lo dije mal antes, ups :sweat_smile:, así que le puse un edit al otro por las dudas así no confundo a nadie).

1 me gusta

¡Tenés razón! No pueden haber repetidos. Pero, ¿Por qué se rompería mí código al hacer esta validación “innecesaria”? Hmmm… Un misterio que espero que pronto sea resuelto :thinking:

¡Hola!

Si no entiendo mal, en tu segment tree trabajás con la noción inclusive/exclusive, es decir si hacés una query(i,j), estás obteniendo la suma en el intervalo [i,j) (incluyendo i, y excluyendo j). Lo cual es la forma recomendada de pensar al Segment Tree :slight_smile:

Veamos entonces lo que pasa en este if

Al recorrer en orden creciente por peso, la condición en palabras dice que si hay dos luchadores consecutivos en este orden con mismo peso, entonces el luchador i-ésimo en este orden domina a todos los luchadores con altura entre [0,h). ¡Eso falla!, ¿Qué pasa en el caso de que haya un luchador con menor peso (estricto) y misma altura? No estaríamos considerando que i lo domina, cuando en realidad sí lo hace.

Como ejemplo, fijate lo que pasa en este caso:

3
2 4
2 3
1 4

Fijate que si agarrás tu código tal cual como está, pero al final hacés la query en [0,h+1) sacás 100/100 (al igual que ariloc, me tomé la libertad de hacer un envío en el juez para verificarlo).

2 Me gusta

¡Ah listo! ¡¡¡Mala mia!!! Ya entendí todo jajaja.
Muchas gracias por aclararme :blush:

1 me gusta