牛客練習賽53 E 老瞎眼 pk 小鮮肉

2022-05-05 11:54:10 字數 1694 閱讀 8455

problem

這題的題意大概是

給出一段長度為\(n\) 的區間

\(q\)次詢問求 \(l\)~ \(r\) 這個區間內 最短的一段區間 \(l\)~\(r\)

使得 \(\oplus_^ a_j= 0\)

\(l<=l

誒 離線麼?樹狀陣列好像不好做啊 因為大多數人只會單點修改區間修改和差分吧

考慮離線+線段樹

我們先記錄乙個 \(sum_i = \oplus_^i a_j\)

那麼我們用乙個類似桶一樣的東西 \(pos_i\) 記錄上乙個出現\(sum_i\) 的位置

顯然這題是個單點修改 求區間最小值

考慮移動 右指標 \(r\)

把詢問的右端點為\(r\) 的存在一起 這樣就省下來乙個排序

我們要記錄 \(l\) 點對區間的貢獻

應該反過來做 考慮 \(sum_j\) 最後一次出現的位置 \(pos_\)

然後對 \(pos_\) 進行單點修改 能保證這個肯定對於\(pos_\)這個點來說向右偏移最小的值使得異或和為0

因為移動的是右端點 右端點往右的區間和當前區間是互為獨立的 或者換句話說 右端點往右的區間對當前區間是沒有貢獻的即對答案不會影響

然後直接大力查詢 \(query(l,r)\) 就可以了

#includeusing namespace std ;

int n , q ;

const int n = 5e5 + 5 ;

int sum[n] ;

vector < pair < int , int > > v[n] ;

int mn[n << 2] ;

int pos[n << 2] ;

int used[n] ;

int ans[n << 1] ;

inline void build(int l , int r , int rt)

inline void change(int x , int l , int r , int rt , int val)

int mid = l + r >> 1 ;

if(x <= mid) change(x , l , mid , rt << 1 , val) ;

else change(x , mid + 1 , r , rt << 1 | 1 , val) ;

mn[rt] = min(mn[rt << 1] , mn[rt << 1 | 1]) ;

}inline int query(int a , int b , int l , int r , int rt)

#define fi first

#define se second

signed main()

for(register int i = 1 ; i <= q ; i ++) ) ;

} build(1 , n , 1) ;

for(register int i = 1 ; i <= n ; i ++)

for ( auto x : v[i] ) ans[x.se] = query(x.fi , i , 1 , n , 1) ;

} for(register int i = 1 ; i <= q ; i ++) printf("%d\n" , ans[i] == int_max ? -1 : ans[i]) ;

return 0 ;

}

牛客練習賽53 老瞎眼 pk 小鮮肉 線段樹思維

傳送門 給定長度為n nn的陣列,q qq個詢問 每次問 l,r l,r l,r 內最小的區間長度 l,r l,r l,r 使得al al 1 ar 0 a l oplus a oplus a 0 al al 1 a r 0 明顯需要預處理 如果做乙個異或字首和pre x pre x pre x 那...

牛客練習賽53 ABC

a 簡單dp include define ll long long using namespace std const ll mod 1e9 7 ll d 1000000 2 ll n intmain cout d n 1 d n 0 mod return0 b 分塊 include define...

牛客練習賽53 B, C, E 題解

b 美味果凍 更換一下列舉順序得到 容易發現 i 為 j,2j 2j,3j t 1 j,t j 時後面向下取整的結果是一樣的,分塊計算即可,j 次冪通過 j 1 次冪 o 1 得到,時間複雜度為 o nlogn include using namespace std typedef long lon...