LuoguP4704 Espada Tai Chi

Titulo

La prueba requirió que Bob cortara n cuerdas lo más rápido posible.

Los puntos finales de todas las cuerdas son diferentes entre sí, por lo que hay 2n puntos finales. Estos puntos finales están atados en un círculo y distribuidos equidistantemente. Numeramos estos puntos finales en sentido horario de 1 a 2n.

Cada vez que Bob corta una línea recta, puede cortar todas las cuerdas que cruzan esta línea recta y quiere saber cuántas veces puede cortar todas las cuerdas.

\ (n <= 2 * 10 ^ 5 \)

Portal

Solución

Romper la cadena primero

Podemos pensar en eso para un segmento de línea que originalmente existía en el anillo, podemos marcar la posición de sus dos puntos en la cadena
y una línea recta cruza este segmento de línea, lo que significa que debe haber una espada Bod Taiji en el arco en los dos extremos de este segmento de línea. Punto final de la línea dibujada

Entonces solo garantizamos:

Debe haber un punto de interrupción entre dos puntos en el círculo con la misma marca

Considera lo codicioso:

Para dos puntos con la misma marca, es mejor establecer el punto de ruptura en el punto final derecho, ya que puede romper más puntos con la misma marca

Además, también necesitamos encontrar el primer punto de interrupción

(Robé esta imagen, el autor de la imagen lo lamenta)


Por ejemplo, en la imagen de arriba, hay tres puntos de interrupción, pero solo se necesita una línea recta. Si
lo piensa, puede saber que el orden de la enumeración del punto de interrupción afecta el resultado final.

Debido a que debe haber puntos finales entre puntos finales, las distancias de punto final más cortas se enumerarán mejor como puntos de interrupción que las distancias de punto final más largas

Entonces, encontramos directamente la distancia mínima del punto final y enumeramos los puntos de corte iniciales

Pasado

Pensemos en su complejidad: establezca la distancia mínima del punto final en d, de
modo que la distancia entre cada punto final debe ser mayor que el espacio d, y la elección del punto de corte será la derecha del siguiente segmento de línea que no se ha roto. Punto final, por lo que para encontrar el siguiente punto de interrupción, puede directamente + d en esta posición, y luego enumerar hacia atrás uno por uno.
Entonces la complejidad total es:
\ (O (d (nodo inicial de enumeración) * (2 * n / d) (Para cada nodo inicial, la posición se recurre hacia atrás)) \)

Código

#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define ll long long
#define get getchar()
in int read()
{
    int t=0,x=1;char ch=get;
    while((ch<'0'||ch>'9')&&ch!='-')ch=get;
    if(ch=='-')x=-1,ch=get;
    while(ch<='9'&&ch>='0')t=t*10+ch-'0',ch=get;
    return x*t;
}
const int _=8e5+5;
int n;
struct edge{
	int l,r;
}a[_];
int to[_];
in int dis(int x,int y)
{
	return min(y-x,2*n-y+x);
}
int main()
{
    n=read();
    int minx=0x3f3f3f3f,xx;
    for(re int i=1;i<=n;i++)
    {
    	a[i].l=read(),a[i].r=read();
	if(a[i].l>a[i].r) swap(a[i].l,a[i].r);
	to[a[i].r]=a[i].l;
	to[a[i].l+2*n]=a[i].r;
	to[a[i].r+2*n]=a[i].l+2*n;//倍长区间,标记每个区间右端点对应的左端点
	if(minx>dis(a[i].l,a[i].r)){
    	    minx=dis(a[i].l,a[i].r);
	    xx=i;	//记录最小距离的区间
	}
    }
    int st,en,ans=0;
    if(a[xx].r-a[xx].l==minx)
	st=a[xx].l,en=a[xx].r;
    else en=a[xx].l+2*n,st=a[xx].r; //标记最小距离区间起始点与结束点
    int len=dis(a[xx].l,a[xx].r);
    for(re int i=st;i<=en;i++)
    {
    	int last=i;ans=0;//last记录上一个断点
	for(re int j=i+len;j<i+2*n;j++)
    	    if(to[j]>last) ans++,last=j,j+=len; //判断条件是如果当前区间不会被上一个断点断开,则新开一个断点
    }
    cout<<(ans)/2+1<<endl;
    return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/yzhx/p/12723430.html
Recomendado
Clasificación