fly(樹狀陣列)

2021-08-09 03:00:41 字數 2298 閱讀 4455

10.7

演算法1:

直接按照題目描述計算鬼畜值.容易發現,雖然第一象限內有無數個點,但只被一條線段經過的點的鬼畜值一定是0,所以我們只考慮至少被兩條線段經過的點,這樣的點最多有n^2個,去去重就可以按照定義算鬼畜值了.複雜度至少為o(n^2),視後續的處理方式時間複雜度可能更高.

可以得到n<=100時的20分.

演算法2:

仔細觀察題目中鬼畜值的計算公式,發現實際上是c(x,2),即每一對在這個點相交的線段,對答案貢獻為1,且(a,b)和(b,a)的貢獻只算1次.因此我們只需要計算c(n,2)對線段中有幾對是相交的.如果直接兩兩判斷是否相交,複雜度o(n^2).

依然只能得到n<=100時的20分.

演算法3:

考慮線段相交的性質.顯然有這樣的結論:0 < a < b,0 < c < d,那麼在(0,a),(c,0)之間連線段,在(0,b),(d,0)之間連線段,這樣的兩條線段在第一象限一定沒有交點.

我們自然得出:答案就是x[1],x[2]…x[n]這個序列的逆序對個數.

考場上這個結論可以通過大樣例進行檢驗.

採用經典的樹狀陣列或分治法在o(nlogn)的時間內求出逆序對數目即可.

可以得到n<=100000時的40分.

演算法4:

可能有的選手對自己的常數非常自信,試圖用o(nlogn)的方法直接ac本題.

如果沒有特殊的壓記憶體技巧,將因為32mb記憶體限制下,開不出1e7的int陣列得到記憶體超限的0分.

出題人估計考場上不會出現能夠把時間和空間常數都用此演算法卡進本題限制的選手.

演算法5:

考慮樹狀陣列演算法,我們需要求出第i個元素和前面i-1個元素形成的逆序對個數.

整個序列由若干段等差數列組成(不超過a段).而第i個元素前面的i-1個元素也可以分成不超過a段等差數列.在每段等差數列內大於第i個元素的元素個數可以o(1)求出,因此o(a)的時間內即可求出第i個元素和前面i-1個元素組成的逆序對數.時間複雜度o(na).

可以得到a<=10時的20分.結合演算法3可以得到60分.

演算法6:

x[1]=a的資料告訴我們,x[i]=i*a%mod

假設x[i]=x[i-1]+a(也就是x[i-1]+a < mod),且x[i-1]和前面所有數字形成了m個逆序對,同時,除去x[i-1]和x[i]所在的等差數列,x[i]前面的所有數字可以分成k段等差序列,那麼x[i]將和前面所有數字組成m-k個逆序對.

原因在於:每段等差序列中必然有乙個數字和x[i-1]能組成逆序對,但不能和x[i]組成逆序對.那麼每段等差數列的貢獻都會減1.

因此我們可以o(1)從x[i-1]的貢獻得到x[i]的貢獻.

如果x[i] < a,不存在對應的x[i-1],我們需要直接計算它的貢獻.前面有i-1個數字,我們數出有多少個數字不產生貢獻(即小於x[i]的數字個數),即可求出有多少個數字形成了逆序對.用樹狀陣列維護小於a的所有數值,可以在o(loga)的時間內完成一次這樣的計算.小於a的數字至多有a個,所以這一部分的時間複雜度為o(aloga),空間複雜度為o(a)

總的時間複雜度為o(aloga+n)

可以得到x[1]=a的20分.

演算法7:

演算法6幾乎就是滿分做法了.現在x[1]!=a,我們只需針對最開始的一段不完整等差數列加一些特判就可以通過本題.

可以得到100分.

演算法8:

實際上存在更加優越的演算法,複雜度為o(aloga),不需要帶有乙個o(n)

考慮演算法6,7中我們都把整個序列劃分為了o(a)段.實際上同一段中所有元素的貢獻是乙個等差數列的形式,可以直接求和.細節可能較多.

#include 

#include

#include

#include

#define ll long long

#define n 100010

using

namespace

std;

int n, x, a, mod;

ll ans;

int c[n];

void add( int x )

int query( int x )

int main()

else now += a;

if( !cnt ) continue;

if( now <= a )

else res -= ( now > x ? cnt : cnt - 1 );//第乙個迴圈不全

ans += res;

}printf("%i64d", ans);

return

0;}

樹狀陣列1 樹狀陣列入門

仔細看一下,發現tree的每乙個節點的高度並不是隨意的,而是由它轉成二進位制之後末尾連續零的數量決定的,連續零的數量加1,就是高度,例如 3 11 零的數量為0,加1等於1,所以它的高度就是1 6 110 零的數量為1,加1等於2,所以它的高度就是2 8 1000 零的數量為3,加1等於4,所以它的...

樹狀陣列 瞎bb 樹狀陣列

樹狀陣列是乙個利用一維陣列和位運算組成的求解區間問題的高效資料結構,其構造如圖所示 首先,我們要用它解決單點修改 區間查詢的操作。根據這張圖我們建立乙個陣列bit,下標就是圖中顯示的十進位制數。bit i 就表示了圖中所示的一段區間的和,例如bit 6 sum 5,6 bit 4 sum 1,4 下...

樹狀陣列 二維樹狀陣列模板

樹狀陣列模板 int lowbit int x int add int x,int val int que int x 模板題 題解 include include include using namespace std int c 300000 rank 300000 int n int lowb...