傳送門
給定長度為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]
那麼問題就轉化為[l−
1,r]
[l-1,r]
[l−1,r
]找到最小的區間[l,
r]
[l,r]
[l,r
]滿足pre
[l]⊕
pre[
r]
pre[l]\oplus pre[r]
pre[l]
⊕pre
[r]
此時區間為[l+
1,r]
[l+1,r]
[l+1,r
] 就是找兩個最相近的數,似乎不是很好弄
考慮離線做法,如果按照r
rr端點排序
那就維護乙個變數idid
id一路加到r
rr去,期間一直更新前面那些相同的數
也就是讓w[i
]w[i]
w[i]
表示a
ia_i
ai和右邊第乙個和a
ia_i
ai相同的數的距離l,
r]
[l,r]
[l,r]中
因為按照r
rr排序,所以端點r
rr滿足
因為查詢線段樹實在[l,
r]
[l,r]
[l,r
],所以左端點也滿足
#include
using
namespace std;
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
const
int maxn =
2e6+10;
const
int inf =
1e9;
struct p
}d[maxn]
;int a[maxn]
,last[maxn]
;int w[maxn]
,n,q,ans[maxn]
;void
build
(int rt,
int l,
int r)
void
update
(int rt,
int l,
int r,
int index,
int val)
update
(lson,index,val)
;update
(rson,index,val)
; w[rt]
=min
( w[ls]
,w[rs]);
}int
ask(
int rt,
int l,
int r,
int l,
int r)
intmain()
for(
int i=
1;i<=q;i++
)sort
( d+
1,d+
1+q )
;int num =1;
build(1
,1,n+1);
for(
int i=
1;i<=q;i++
) ans[d[i]
.id]
=ask(1
,1,n,d[i]
.l,d[i]
.r );}
for(
int i=
1;i<=q;i++
)}
牛客練習賽53 E 老瞎眼 pk 小鮮肉
problem 這題的題意大概是 給出一段長度為 n 的區間 q 次詢問求 l r 這個區間內 最短的一段區間 l r 使得 oplus a j 0 l l 誒 離線麼?樹狀陣列好像不好做啊 因為大多數人只會單點修改區間修改和差分吧 考慮離線 線段樹 我們先記錄乙個 sum i oplus i a ...
老瞎眼 pk 小鮮肉 線段樹 區間離線
題意 給出一段長度為n的序列,q次查詢區間 l,r 內異或為0最短子區間長度。思路 假設區間 l,r 異或為0,那麼 1,l 1 的異或值等於 1,r 的異或值。那麼對於每個點,我們存以它為右端點的區間異或值為0的最短區間長度,再將查詢區間按右端點公升序排列。然後利用線段樹,從左到右遍歷 在這個點對...
牛客練習賽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...