diapazonunda seqment ağacı quraq və əvvəlcə onu sıfırlayaq. Ticarətçi [l_i; r_i] yaşayış məntəqələrində papaqlar satırdısa və qiyməti p_i ilə başlayırdısa, [l_i; r_i] seqmentini əsas seqmentlərə ayıraq: [lx_1; ry_1], [lx_2; ry_2], ..., [lx_k; ry_k]. Sonra [lx_q; ry_q]~(1 \le q \le k) seqmentinə
mənasını əlavə edək.
Məsələn, n = 5 və ilk ticarət 2-dən 5-ə qədər nömrəli şəhərləri əhatə etdiyini düşünək və 4 qiyməti ilə başlayırıq. Sonra seqmenti əsas seqmentlərə çevriləcəkdir: [2; 2], [3; 3], [4; 5]. İlk əməliyyatdan sonra seqment ağacı bu şəkildə görünəcək:
Əgər əsas seqment qiymətini saxlayırsa, bu o deməkdir ki:
Ticarətçi bütün -dan -yə qədər şəhərlərdə papaqlar satmışdır.
şəhərində papaq qiymətinə satılırdı, a + 1 şəhərində p + 1 qiymətinə və beləliklə, şəhərində qiyməti p + b - a qədər olurdu.
[left; right] (ticarətçinin ticarət etdiyi seqment) sorğusunun [lpos; rpos] diapazonunda işlənməsi prosedurunu nəzərdən keçirək, əgər papağın başlanğıc qiyməti -dirsə.
Sol alt seqmentdə ticarətçi qiymətindən başlayaraq len = min(mid, right) - left + 1 şəhərlərində papaqları satacaqdır. Sağ alt seqmentdə ticarətçinin gələcəyi şəhərdə papağın ilk qiyməti x + len olacaqdır. Beləliklə, [max(left, mid + 1), right] aralığında ticarət x + len qiymətindən başlanacaq. Ancaq əgər len < 0-dursa (bu mümkündür, əgər sorğu aralığının bütün seqmenti sağ alt seqmentdədirsə), len = 0 qoymalıyıq.
seqmentini nəzərdən keçirdikdə, bu seqmentin iki alt seqmenti var: və [m + 1; b]. Əgər şəhərində ticarətçi papağı qiymətinə satırsa, onda m + 1 şəhərində onun qiyməti p + m + 1 - a olacaqdır.
Sorğuların işlənməsi prosesində maksimumu dəstəkləyən dəyərlərin itələməsini tətbiq edək.
Cavabın çıxışını vermək üçün ağac boyunca keçərək bütün dəyərləri yarpaqlara qədər itələyib və nəticəni çıxış edək.
Nümunə
Nümunədə verilmiş iki sorğunun icrasını nəzərdən keçirək. Sorğu seqmentlərini əsas seqmentlərə bölək:
[1; 3] = [1; 3];
[2; 4] = [2; 2] + [3; 3] + [4; 4].
Alqoritm realizasiyası
Seqment ağacını saxlamaq üçün SegTree massivini elan edək.
#define MAX 300010
long long SegTree[4*MAX];Push funksiyası zirvəsindən onun davamçılarına dəyəri itələyir.
void Push(int v, int lpos, int mid, int rpos)
{
if (SegTree[v])
{
SegTree[2 * v] = max(SegTree[2 * v], SegTree[v]);
SegTree[2 * v + 1] = max(SegTree[2 * v + 1],
SegTree[v] + mid - lpos + 1);
SegTree[v] = 0;
}
}Update funksiyası qiymətindən başlayaraq [left; right] aralığında papaqların satışını yerinə yetirir.
void Update(int v, int lpos, int rpos, int left, int right,
long long x)
{
if (left > right) return;
if ((lpos == left) && (rpos == right))
SegTree[v] = max(SegTree[v], x);
else
{
int mid = (lpos + rpos) / 2;
Push(v, lpos, mid, rpos);
int len = min(mid, right) - left + 1;
if (len < 0) len = 0;
Update(2 * v, lpos, mid, left, min(mid, right), x);
Update(2 * v + 1, mid + 1, rpos, max(left, mid + 1),
right, x + len);
}
}PrintResult funksiyası daxili zirvələrdən dəyərləri yarpaqlara itələyir və massivinin son vəziyyətini çıxış edir.
void PrintResult(int v, int lpos, int rpos)
{
if (lpos == rpos)
printf("%lld ", SegTree[v]);
else
{
int mid = (lpos + rpos) / 2;
Push(v, lpos, mid, rpos);
PrintResult(2 * v, lpos, mid);
PrintResult(2 * v + 1, mid + 1, rpos);
}
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
scanf("%d %d", &n, &m);
memset(SegTree,0,sizeof(SegTree));sorğuları işlədirik.
for(i = 0; i < m; i++)
{
scanf("%d %d %lld", &l, &r, &x);
Update(1,1,n,l,r,x);
}Nəticəni çıxış edirik.
PrintResult(1,1,n);
printf("\n");