trang chủ / bài tập / sprinklers / lời giải

Vòi Phun Nước

Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Tác giả: huunguyenhuunguyen

Lời giải: Vòi Phun Nước (Sprinklers)

Nhận xét quan trọng

Trước hết, cần xác định điều kiện để một điểm (x,y) là hợp lệ:

  • Được tưới nước: tồn tại vòi tại (i,j) với ixjy.
  • Được bón phân: tồn tại vòi tại (i,j) với ixjy.

Do các vòi tạo thành một hoán vị (mỗi hàng và cột có đúng một vòi), ta có thể xác định:

  • Điểm (x,y) được tưới nước tồn tại ix sao cho A[i]y (với A[i] là tọa độ y của vòi ở cột x=i).
  • Điểm (x,y) được bón phân tồn tại ix sao cho A[i]y.

Định nghĩa:

  • lft[y] = giá trị nhỏ nhất của x sao cho (x,y) hợp lệ (tức là tọa độ x nhỏ nhất để cột đó "kích hoạt" phân bón cho y).
  • top[x] = giá trị y lớn nhất sao cho x có thể là cạnh phải của một hình chữ nhật.

Thuật toán

Bài toán yêu cầu đếm số cặp (x1,y1,x2,y2) với x1<x2, y1<y2 sao cho toàn bộ hình chữ nhật [x1,x2]×[y1,y2] hợp lệ.

Ý tưởng chính: Duyệt x2 từ 1 đến N1, với mỗi x2 cố định, đếm số cặp (x1,y1,y2) hợp lệ.

Tính top[i]lft[j]
  • top[i]=max(A[i],A[i+1],,A[N1]): y-tối đa để cột i có thể là cạnh trái.
  • lft[j]: với mỗi j, đây là x-tối thiểu để điểm (x,j) hợp lệ. Tính bằng cách duyệt giảm dần: với vòi tại cột i (tọa độ yA[i]), cập nhật tất cả j<A[i]lft[j]=i.
Đếm tổng hình chữ nhật

Với x2 cố định, số cặp (y1,y2) hợp lệ với x1 cố định là: tot(x2)=i·top[i]·(top[i]+1)2 (tổng số cặp (y1,y2) với 0y1<y2top[i], nhân với số lựa chọn x1[0,i1]).

Trừ các hình chữ nhật không hợp lệ (bad)

Một hình chữ nhật không hợp lệ khi có điểm (x1,y1) không hợp lệ, tức là x1<lft[y1].

Với j= cận dưới của vùng y được xét, ta chia thành 2 trường hợp:

  1. y1<j: Dùng công thức trực tiếp bad2=i·(j·jj(j1)/2)(modMOD).
  2. y1j: Dùng prefix sum: bad1=y=jtop[i]1lft[y]·(Ny)(Ntop[i])·y=jtop[i]1lft[y].

Với mỗi x2=i, con trỏ j di chuyển đơn điệu (do tính đơn điệu của lft), nên tổng thời gian xử lý là O(N).

Tổng kết

ans=i=1N1(tot(i)bad(i))(mod109+7)

Độ phức tạp

  • Thời gian: O(N)
  • Bộ nhớ: O(N)

Điểm mấu chốt là tính đơn điệu của mảng lft (không tăng khi j tăng) và top (không tăng khi i tăng), cho phép dùng hai con trỏ và prefix sum để giải trong O(N).


Bình luận

Không có bình luận tại thời điểm này.

gnatmake 12.2.0 a68g 3.1.2 nasm 2.16.1 as_x64 2.46 awk 1.3.4 gcc 16.1.0 csc 6.12.0.200 g++ 16.1.0 g++-themis 16.1.0 g++17 16.1.0 g++20 16.1.0 g++23 16.1.0 clang++ 22.1.6 dmd 2.112.0 dart 3.12.1 gforth 0.7.3 gfortran 12.2.0 go 1.26.3 groovyc 5.0.6 javac 25.0.3 node 26.2.0 kotlinc 2.3.21 sbcl 2.2.9 lua 5.4.8 nim 2.2.10 fpc 3.2.2 fpc-themis 3.2.2 perl 5.36.0 php 8.5.6 pike 8.0 pypy3 7.3.23 python3 3.14.5 racket 8.7 ruby 4.0.5 rustc 1.96.0 csc 5.3.0 ctoj-scratch 0.0.1 sed 4.9 tclsh 8.6 bun 1.3.14 deno 2.8.1 v 0.5.1 zig 0.16.0