多校 HDU6601(主席樹 線段樹 RMQ)

2021-09-26 02:34:20 字數 1822 閱讀 9478

q:給n(1≤n≤1e5)個任意長度的三角形,長度為a1,a2,…an(1≤ai≤1e9),q(1≤q≤1e5)組詢問,每組詢問給出l和r,在第l個到第r個的長度中選三個組成三角形使其周長最大,不存在輸出-1

a:首先這三個長度按大小排序時的標號顯然必定是連續的:

比方說設三個長度a>b>c, 如果a是這個區間中最大的數,b,c肯定是次大的數和次次大的數,因為這個時候b和c已經盡可能大了,假如加起來還是不能大於a,那麼對於取a為最大數的情況下,陣列裡就莫得滿足條件的b和c了

所以我們也就是按這個順序找(a=最大,b=次大,c=次次大),(a=次大,b=次次大,c=次次次大),……以此類推直到c為區間中最小數中是否有滿足b+c>a的,有的話break,一直都莫得就為-1

那麼要怎麼找才不會tle呢?這個時候我們需要推乙個規律。

我們在最壞情況下需要找多少次才能找到乙個滿足條件的三元組(a,b,c)呢?

找不到說明b+c<=a,最壞的可能就是取等於,一直找到1e9,顯然是乙個斐波那契數列,f(1)=1,f(2)=1,f(3)=f(2)+f(1),f(4)=f(3)+f(2),……,f(45)>1e9,所以最壞情況下找45組(假如這個區間有這麼多數的話),一定會找到乙個滿足條件的三元組。

所以對於乙個查詢,我們找這個區間的最大,次大,……45大就好啦(是指從大往小找)

有挺多方法找的:

主席樹:主席樹可以找到第k大,套個板子,它是乙個乙個找(最大,次大,…),看看符不符合就好了

注意!kuangbin板子中指的第k大的數是指從小到大的第k個數,我們要從大到小找,稍加修改即可

另:一般來說由於主席樹帶乙個很大的常數,跑起來時間是線段樹的5倍左右。但是這道題的資料應該是隨機資料(隨機資料主席樹不用找45個(這個畢竟是特殊情況)就能找到符合條件的了,線段樹卻需要一次性處理45個),所以反而卡線段樹(可做優化以ac)不卡主席樹

線段樹:線段樹找前45大,它是一次性找出45個來,需優化

rmq:找前45大,同線段樹

主席樹ac**:(套的kuangbin的板子,據說某些陣列在這道題裡並不需要開?我也不嘰道我只是隻菜雞.jpg等我徹底弄明白線段樹再看。。)

time:1294ms

memory:74200kb

#includeusing namespace std;

#define ll long long

const ll maxn=100010;

const ll m=maxn*30;

ll n,q,m,tot;

ll a[maxn],t[maxn];

ll t[maxn],lson[m],rson[m],c[m];

void init_hash()

ll build(ll l,ll r)

return root;

}ll hashh(ll x)

ll update(ll root,ll pos,ll val)

else

c[newroot]=c[root]+val;

}return tmp;

}ll query(ll left_root,ll right_root,ll k)

else

}return l;

}int main()

while(q--)

else

else

if(flag) break;

step++;

if(step>47) break;

}if(!flag)

printf("-1\n");}}

}}

return 0;

}

線段樹:(之後再補)

rmq:(之後再補)

HDU 6601 三角形 主席樹 斐波那契數列

給n個邊的長度,詢問q次,每次詢問回答能構成的三角形的最大周長。n和q都是1e5 1e51e 5的範圍。先想想如果就給乙個陣列求最大周長三角形的做法。容易想到就是排個序,從大到小列舉n 2次,每次檢查三條邊能不能構成三角形,如果不行,那麼最大的那條邊就沒有其他邊可以跟他組了,其他邊都更小 如果遇到了...

HDU 4866 多校1 主席樹 掃瞄線

終於是解決了這個題目了 不過不知道下一次碰到主席樹到底做不做的出來,這個東西稍微難一點就不一定能做得出 離散化 掃瞄線式的建樹,所以對於某個座標二分找到對應的那顆主席樹,即搜尋出結果即可 因為是掃瞄線式的建樹,找到對應的樹之後,就知道該點上面的線段有多少條了 其他就是普通主席樹的操作了 主席樹裡面維...

HDU 4893 2014多校三 線段樹

給定乙個初始都為0的序列,有三種操作,前兩種比較正常,乙個是對某個位置的數add k,另乙個是query區間和。然後比較麻煩的是第三個操作,把某個區間裡面的每個值改成離它最近的fibonacci數,如果存在左右兩個離它近的,優先取左邊數值小的 一看到前兩個操作馬上就想上手敲樹狀陣列,後來看到第三個就...