1. 程式人生 > >【OJ3358】簡單的數列題

【OJ3358】簡單的數列題

大小 一個 display 最優 右移 暴力 兩個 交換 區間修改

給定兩個長度為 \(n\) 的數列 \(a\)\(b\),有 \(m\) 個操作,操作分為三類:

  • \(1\) \(l\) \(r\) \(w\) :將數列 \(a\) 中區間 \([l,r]\) 內所有數加上 \(w\) ;

  • \(2\) \(x\) \(y\) :交換 \(b_x\)\(b_y\) ;

  • \(3\) \(l\) \(r\) : 求 \(\displaystyle \max_{i=l}^r \{a_i\cdot b_i\}\) .

\(1\le n,m\le 10^5,\ 0\le a_i\le 10^7,\ 0\le b_i\le 10^5,\ 0\le w_i\le 100\)

.


考慮分塊。每一塊就直接維護 max{\(a_i\cdot b_i\)} .

然後我們看操作。第二個操作十分簡單,直接交換後暴力重構即可。第一個操作區間修改,兩邊的塊也可以直接修改。關鍵在於中間的塊。

我們要求的元素的權值 \(w_i=cnt\cdot b_i+c_i\). \( \(cnt\) 為整塊累加的值, \(c_i=a_i\cdot b_i\))

我們發現這其實是一個一次函數。我們對於每個 \(cnt\) 要找到最大的 \(w_i\) .

我們考慮對上面的式子變形,得到: \(c_i=-cnt\cdot b_i+w_i\).

我們要求的 \(w_i\) 即為斜率為 \(-cnt\)

的直線經過所有 \((b_i,c_i)\) ,與y軸的截距。顯然最大截距的直線一定是凸殼的一條切線。同時我們發現隨著 \(cnt\) 的增大,最大值的點的位置單調向右移動。

這樣我們對於每一塊按 \(b\) 值排序,然後維護一個上凸殼。每次整塊增加時直接打標記,然後向右移動最大值位置。

單次修改復雜度為 $ \displaystyle\frac{n}{S}+S\log n$ , 取塊大小 \(S\)\(\displaystyle \sqrt{\frac{n}{\log n}}\) 復雜度最優為 \(O(\sqrt{n\log n})\)

【OJ3358】簡單的數列題