這題我們可以想到將每個數字變成 \(d\) 進製的數,消滅數可以看成是 \(d\) 進製下原數是這個數 \(d\) 進製下的一段字首。
於是可以使用 \(trie\) 來實現這個過程,於是可以先將這 \(m\) 個原數 insert,然後再去查詢。
乙個數有多個字首,我們可以選擇其中最短的乙個,因為這樣是最優秀的,可以理解為越短的串延伸出來的串就越多,而越長的串則通用性就越差。
於是我們就可以求出是每個數會選擇哪個原數進行消滅,我們可以將狀態存在乙個 long long 裡面,需要做到的就是區間或。
無修改,只有區間或,可以想到使用倍增(st表)來求,因為或有著跟 \(\min\) 和 \(\max\) 一樣好的性質。
code(目前的最優解):
#include#define fi first
#define se second
#define ll long long
#define pb push_back
#define mp make_pair
#define sz(x) ((int)x.size()-1)
#define ms(a,b) memset(a,b,sizeof a)
#define f(i,a,b) for(int i=(a);i<=(b);++i)
#define df(i,a,b) for(int i=(a);i>=(b);--i)
#define debug(b,a) cerr<<"d:";f(i,1,b-1)cerr<<" ";cerr<<" "<<#a<<" => "<<(a)<<" <="<<__line__<<"l"<>1]+1;
f(i,1,n)a[i]=read();
f(i,1,m)b[i]=read();
sort(b+1,b+m+1);
f(i,1,m)
insert(b[i],i);
f(i,1,n)
f(i,1,lg2[n])
f(j,1,n)
f[i][j]=f[i-1][j]|f[i-1][j+(1<<(i-1))];
while(q--)
return 0;
}
題解 P1712 NOI2016 區間
先按照長度排個序,然後依次新增區間。什麼是新增?設這個區間是 l r l,r 新增就是把al al 1,al 2,a r al,al 1 al 2,ar 都加上1 1 其中ai role presentation style position relative aia i表示第 i i 個位置被幾個...
題解 NOI2016區間
two pointer 第一題 大概就是對於一段連續的區間求解,使用兩個指標不斷卡區間的長度直到區間不滿足條件吧。這題只要對區間以長度從小到大排一下序,然後使用兩個指標指向區間。線段樹維護被覆蓋最多次數的節點被覆蓋了多少次。如果滿足條件,由於我們是在第一次判斷的時候發現它滿足條件的,所以最後加入的這...
NOI2016 區間 題解
題目大意 有n個區間,當有m個區間有公共部分時,求m個區間長度的最大值與最小值之差的最小值。思路 按區間的長度從小到大排序,可知連續的幾個區間最優,則用兩個指標指其頭尾,線性掃瞄,再用線段樹區間覆蓋。1 include2 include3 include4 define n 1000009 5 de...