[国家集训队]middle(二分+主席树[中位数思维题])
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                [国家集训队]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 0≥0表示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(二分+主席树[中位数思维题])的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 字节跳动开启今年第二轮员工期权回购 每股
 - 下一篇: 消息称苹果正利用大语言模型改造 Siri