2020CCPC-Estação Mianyang-Joy of Handcraft (árvore de segmento de linha e divisão de fator)

Cavalinho sempre faz alguns artesanatos, que sempre trazem muita alegria. Desta vez, ele constrói um circuito que pode ligar e desligar as lâmpadas periodicamente.

Existem n lâmpadas no circuito, a i-ésima das quais tem um período t i e uma luminância x i. Formalmente, a i-ésima lâmpada será ligada do (2kt i +1) -ésimo segundo ao (2kt i + t i) -ésimo segundo, e será desligada do (2kt i + t i +1) -ésimo segundo ao (2kt i + 2t i) -ésimo segundo, k = 0,1,2, ... Quando a i-ésima lâmpada estiver ligada, sua luminância será x i, caso contrário, sua luminância será 0.

Agora, Little Horse quer saber, para cada segundo do primeiro segundo ao m-ésimo segundo, qual é a luminância máxima entre todas as lâmpadas.

Entrada

A primeira linha da entrada contém um inteiro T (1≤T≤100) - o número de casos de teste.

A primeira linha de cada caso de teste contém dois inteiros n, m (1≤n, m≤10 5) - o número de lâmpadas e o número de inteiros que você precisa para gerar. A soma de n e a soma de m não excederá 2 × 10 5.

Então, nas próximas n linhas, a i-ésima linha contém dois inteiros t i, x i (1≤t i, x i ≤10 5) - o período e a luminância da i-ésima lâmpada.

Resultado

O x-ésimo caso de teste começa com Caso #x :, e a seguir m inteiros. O i-ésimo inteiro indica a luminância máxima entre todas as lâmpadas no i-ésimo segundo. Se nenhuma lâmpada estiver acesa no i-ésimo segundo, produza 0.

Amostra de entrada

3
2 3
1 1
2 2
2 5
1 2
2 3
3 3
1 1
1 2
1 3

Saída de amostra

Case #1: 2 2 1
Case #2: 3 3 2 0 3
Case #3: 3 0 3

Ideia principal:

Existem N lâmpadas, e cada lâmpada tem duas propriedades: Ti, Xi, Xi representa o brilho da lâmpada, Ti representa o ciclo de comutação e o tempo para uma lâmpada acender é de (2ktTi +1) -ésimo segundo ao (2ktTi + T i), k = 0,1,2, ... Agora pergunte o tempo de 1 a M, qual é o brilho máximo por unidade de tempo.

solução:

Não é difícil pensar em usar uma árvore de segmentos de linha para manter o valor máximo. A ideia inicial é atualizar cada lâmpada com seu ciclo de luz, mas essa complexidade definitivamente não é suficiente. Vamos ver como otimizá-la.

Observando o período de luz da lâmpada, podemos descobrir que a extremidade direita do período de luz é T, 3 * T, 5 * T ... O coeficiente na frente de T é um número ímpar que aumenta em sequência e, uma vez que a extremidade direita é determinada, o intervalo também pode ser determinado. Esta propriedade pode ser listada na equação S * T = W , onde S representa o coeficiente antes de T, e W é o tempo de enumeração (de 1 a M). Encontre o fator para W. Se for um número ímpar, então você pode Encontre a lâmpada correspondente com o período de tempo T e, a seguir, modifique o valor máximo no intervalo.

Deve-se notar que para cada conjunto de exemplos, a extremidade direita da árvore do segmento de linha é determinada, porque pode haver uma extremidade direita de uma lâmpada> M, mas a extremidade esquerda <M, eu obtenho diretamente max (3 * M, 3 * período máximo da lâmpada )

Código aceito

#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;

#define sc scanf
#define Max(a, b) a = max(a, b)
typedef long long ll;
const int N = 5e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

int sum[N], mxt[N * 4];
int t[N], x[N];
int n, m;

#define ls o << 1
#define rs ls | 1
void Build(int o, int L, int R) {
	mxt[o] = 0;
	if (L == R)
		return;
	int mid = (L + R) >> 1;
	Build(ls, L, mid);
	Build(rs, mid + 1, R);
}
void Pushdown(int o) {
	Max(mxt[ls], mxt[o]), Max(mxt[rs], mxt[o]);
}
void Add(int o, int L, int R, int l, int r, int k) {
	if (L >= l && R <= r)
		Max(mxt[o], k);
	else {
		Pushdown(o);
		int mid = (L + R) >> 1;
		if (mid >= l)
			Add(ls, L, mid, l, r, k);
		if (mid < r)
			Add(rs, mid + 1, R, l, r, k);
	}
}
int Ask(int o, int L, int R, int x) {
	if (L == R)
		return mxt[o];
	else {
		Pushdown(o);
		int mid = (L + R) >> 1;
		int tot = 0;
		if (mid >= x)
			Max(tot, Ask(ls, L, mid, x));
		else
			Max(tot, Ask(rs, mid + 1, R, x));
		return tot;
	}
}

int main()
{
	int Cas = 0;
	int T; cin >> T;
	while (T--) {
		sc("%d %d", &n, &m);

		int mx = 0;
		for (int i = 1; i <= n; i++) {
			sc("%d %d", &t[i], &x[i]);
			Max(sum[t[i]], x[i]);
			Max(mx, t[i]);
		}

		int ri = max(3 * mx, 3 * m);  // 最右端点
		for (int i = 1; i <= ri; i += 2) {
			for (int j = i; j <= ri; j += i)
			{
				if (i & 1) {  // i是j的奇数因子
					int tmp = j / i; // 时间
					if (!sum[tmp])
						continue;
					int r = j, l = j - tmp + 1;  // 区间
					Add(1, 1, ri, l, r, sum[tmp]);  // 区间标记最值
				}
			}
		}
		printf("Case #%d: ", ++Cas);
		for (int i = 1; i <= m; i++) {
			printf("%d", Ask(1, 1, ri, i));
			if (i == m)
				puts("");
			else
				printf(" ");
		}
		for (int i = 1; i <= n; i++)  // 清空
			sum[t[i]] = 0;
		Build(1, 1, ri);   // 线段树清空
	}
	return 0;
}

 

 

Acho que você gosta

Origin blog.csdn.net/weixin_43851525/article/details/109436883
Recomendado
Clasificación