日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

技术情报局(笛卡尔树)

發布時間:2023/12/3 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 技术情报局(笛卡尔树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

problem

有這樣一道簡單題:給定一個序列求所有區間的最大值的和。

還有這樣一道簡單題:給定一個序列求所有區間的乘積的和。

眾所周知:簡單題 + 簡單題 = 簡單題。

所以,給定一個長為 nnn 的正整數序列,定義一個區間的權值是該區間的數的乘積乘上該區間的最大值,
求該序列所有區間的權值和,答案對 modmodmod 取模。

solution

套路地枚舉最大值。

得到其作為最大值時管轄的范圍 [l,r][l,r][l,r]

然后就是計算所有的情況,?l≤i<pos?pos<j≤r∏k=ijak?apos\forall_{l\le i<pos}\forall_{pos<j\le r}\prod_{k=i}^ja_k*a_{pos}?li<pos??pos<jr?k=ij?ak??apos?

這種橫跨中間點需要左右的子樹信息的操作,很容易聯想到二叉樹之類的樹形結構。

這里有“最大值”要求,所以我們選擇建立大根堆的笛卡爾樹。

天然地左右兩個兒子的子樹內的點都是小于自己權值的。

然后就是搜樹,在搜笛卡爾樹時從下往上地類似線段樹維護區間內一段連續前綴,一段連續后綴,整體區間的相關信息轉移合并。

code

#include <bits/stdc++.h> using namespace std; #define maxn 10000005 #define int long long int n, s, l, r, mod; vector < int > a;namespace GenHelper {unsigned z1, z2, z3, z4, b;unsigned rand_() {b = ((z1 << 6) ^ z1) >> 13;z1 = ((z1 & 4294967294U) << 18) ^ b;b = ((z2 << 2) ^ z2) >> 27;z2 = ((z2 & 4294967288U) << 2) ^ b;b = ((z3 << 13) ^ z3) >> 21;z3 = ((z3 & 4294967280U) << 7) ^ b;b = ((z4 << 3) ^ z4) >> 12;z4 = ((z4 & 4294967168U) << 13) ^ b;return (z1 ^ z2 ^ z3 ^ z4);}}std::vector<int> get (int n, unsigned s, int l, int r) {std::vector<int> a;using namespace GenHelper;z1 = s;z2 = unsigned((~s) ^ 0x233333333U);z3 = unsigned(s ^ 0x1234598766U);z4 = (~s) + 51;for (int i = 1; i <= n; i ++) {int x = rand_() & 32767;int y = rand_() & 32767;a.push_back(l + (x * 32768 + y) % (r - l + 1));}return a; }int root, ans; int lson[maxn], rson[maxn]; struct node { int pre, suf, all; };void build() {for( int i = 0;i < n;i ++ ) lson[i] = -1, rson[i] = -1;stack < int > sta;for( int i = 0;i < n;i ++ ) {while( ! sta.empty() and a[sta.top()] <= a[i] ) lson[i] = sta.top(), sta.pop();if( ! sta.empty() ) rson[sta.top()] = i;sta.push( i );}while( ! sta.empty() ) root = sta.top(), sta.pop(); }node dfs( int now, int l, int r ) {node L = { 1, 1, 1 }, R = { 1, 1, 1 };if( ~ lson[now] ) L = dfs( lson[now], l, now - 1 );if( ~ rson[now] ) R = dfs( rson[now], now + 1, r );ans = ( ans + a[now] * a[now] % mod * L.suf % mod * R.pre ) % mod;int pre = ( L.pre + L.all * R.pre % mod * a[now] ) % mod;int suf = ( R.suf + R.all * L.suf % mod * a[now] ) % mod;int all = L.all * R.all % mod * a[now] % mod;return { pre, suf, all }; }signed main() {freopen( "tio.in", "r", stdin );freopen( "tio.out", "w", stdout );scanf( "%lld %lld %lld %lld %lld", &n, &s, &l, &r, &mod );a = get( n, s, l, r );build();dfs( root, 0, n - 1 );printf( "%lld\n", ans );return 0; }

總結

以上是生活随笔為你收集整理的技术情报局(笛卡尔树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。