日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[国家集训队]middle(二分+主席树[中位数思维题])

發布時間:2023/12/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [国家集训队]middle(二分+主席树[中位数思维题]) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 點擊查看
  • solution
  • code

點擊查看

solution

簡單口胡一下就跑

考慮二分答案ansansans
區間[x1,x2],x1∈[a,b],x2∈[c,d][x1,x2],x1∈[a,b],x2∈[c,d][x1,x2],x1[a,b]x2[c,d]
大于等于ansansans的設為111,小于ansansans的設為000
如果和≥0\ge 00表示ansansans還可以更大,否則應該變小

發現無論x1,x2x1,x2x1,x2怎么取,有一段是肯定包含的→[b+1,c?1]\rightarrow[b+1,c-1][b+1,c?1]
即,只需要最大化[x1,b],[c,x2][x1,b],[c,x2][x1,b],[c,x2]之間的和,就是一個最大后綴/最大前綴問題

可以利用線段樹求解
對于每一個中位數建立一棵線段樹
發現空間飛了
主席樹硬剛

值域遠大于““定義域””
離散搞tatata

詳情請見下方代碼
?\Downarrow?

code

#include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define int long long #define maxn 20005 int n, m, cnt; int opt[10], root[maxn]; struct array { int val, id; }a[maxn]; struct node { int sum, lsum, rsum, lson, rson; }t[maxn * 30];void pushup( int x ) {t[x].sum = t[t[x].lson].sum + t[t[x].rson].sum;t[x].lsum = max( t[t[x].lson].lsum, t[t[x].lson].sum + t[t[x].rson].lsum );t[x].rsum = max( t[t[x].rson].rsum, t[t[x].rson].sum + t[t[x].lson].rsum ); }void build( int &now, int l, int r ) {now = ++ cnt;t[now].sum = t[now].lsum = t[now].rsum = r - l + 1;if( l == r ) return;int mid = ( l + r ) >> 1;build( t[now].lson, l, mid );build( t[now].rson, mid + 1, r ); }void modify( int lst, int &now, int l, int r, int pos ) {t[now = ++ cnt] = t[lst];if( l == r ) { t[now].sum = t[now].lsum = t[now].rsum = -1; return; }int mid = ( l + r ) >> 1;if( pos <= mid ) modify( t[lst].lson, t[now].lson, l, mid, pos );else modify( t[lst].rson, t[now].rson, mid + 1, r, pos );pushup( now ); }node query( int now, int l, int r, int L, int R ) {if( L <= l and r <= R ) return t[now];int mid = ( l + r ) >> 1;if( R <= mid ) return query( t[now].lson, l, mid, L, R );else if( mid < L ) return query( t[now].rson, mid + 1, r, L, R );else {node lson = query( t[now].lson, l, mid, L, R );node rson = query( t[now].rson, mid + 1, r, L, R );int sum = lson.sum + rson.sum;int lsum = max( lson.lsum, lson.sum + rson.lsum );int rsum = max( rson.rsum, rson.sum + lson.rsum );return { sum, lsum, rsum };} }bool check( int x ) {int ans1 = 0, ans2 = 0, ans3 = 0;if( opt[2] + 1 <= opt[3] - 1 ) ans1 = query( root[x], 1, n, opt[2] + 1, opt[3] - 1 ).sum;ans2 = query( root[x], 1, n, opt[1], opt[2] ).rsum;ans3 = query( root[x], 1, n, opt[3], opt[4] ).lsum;return ans1 + ans2 + ans3 >= 0; }signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) {scanf( "%lld", &a[i].val );a[i].id = i;}build( root[1], 1, n );sort( a + 1, a + n + 1, []( array x, array y ) { return x.val < y.val; } );for( int i = 1;i < n;i ++ )modify( root[i], root[i + 1], 1, n, a[i].id );scanf( "%lld", &m );int ans = 0;while( m -- ) {for( int i = 1;i <= 4;i ++ ) {scanf( "%lld", &opt[i] );opt[i] = ( opt[i] + ans ) % n + 1;}sort( opt + 1, opt + 5 );int l = 1, r = n;while( l <= r ) {int mid = ( l + r ) >> 1;if( check( mid ) ) ans = mid, l = mid + 1;else r = mid - 1;}printf( "%lld\n", ans = a[ans].val );}return 0; }

總結

以上是生活随笔為你收集整理的[国家集训队]middle(二分+主席树[中位数思维题])的全部內容,希望文章能夠幫你解決所遇到的問題。

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