用户工具

站点工具


2020-2021:teams:legal_string:jxm2001:可持久化数据结构_3

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
2020-2021:teams:legal_string:jxm2001:可持久化数据结构_3 [2020/08/18 18:26]
jxm2001
2020-2021:teams:legal_string:jxm2001:可持久化数据结构_3 [2020/09/20 19:30] (当前版本)
jxm2001 [习题三]
行 141: 行 141:
  }  }
  enter(ans);​  enter(ans);​
 + return 0;
 +}
 +</​code>​
 +</​hidden>​
 +
 +==== 习题二 ====
 +
 +[[https://​www.luogu.com.cn/​problem/​P5283|洛谷p5283]]
 +
 +=== 题意 ===
 +
 +给定 $n$ 个互异的数,求前 $k$ 大的区间异或和。
 +
 +=== 题解 ===
 +
 +前缀异或和处理,问题转化为求前 $k$ 大的点对异或和。
 +
 +考虑用优先队列维护每个固定点 $i$ 对配对区间 $[0,i-1]$ 的最佳答案,设 $i$ 的最大答案位置为 $k_i$。则全局最大答案一定为某个 $(k_i,​i)$。
 +
 +弹出全局最大答案,固定点 $i$ 的第二大答案位置一定在区间 $[0,k_i-1]$ 和 $[k_i+1,​i-1]$,将其加入优先队列。
 +
 +重复 $k$ 次即可得到全局前 $k$ 大答案。
 +
 +<hidden 查看代码>​
 +<code cpp>
 +const int MAXN=5e5+5,​MAXM=32;​
 +int root[MAXN],​ch[MAXN*35][2],​val[MAXN*35],​idx[MAXN*35],​cnt;​
 +void Insert(int &k,int p,int id,LL v,int pos){
 + k=++cnt;
 + val[k]=val[p]+1;​
 + if(pos<​0){
 + idx[k]=id;​
 + return;
 + }
 + int dir=(v>>​pos)&​1;​
 + ch[k][!dir]=ch[p][!dir];​
 + Insert(ch[k][dir],​ch[p][dir],​id,​v,​pos-1);​
 +}
 +int query(int lef,int rig,LL v){
 + int pos=MAXM-1,​k1=lef?​root[lef-1]:​0,​k2=root[rig];​
 + while(~pos){
 + int dir=(v>>​pos)&​1;​
 + if(val[ch[k2][!dir]]-val[ch[k1][!dir]])
 + k1=ch[k1][!dir],​k2=ch[k2][!dir];​
 + else
 + k1=ch[k1][dir],​k2=ch[k2][dir];​
 + pos--;
 + }
 + return idx[k2];
 +}
 +LL a[MAXN];
 +struct Node{
 + int ql,​qr,​x,​nxt;​
 + LL v;
 + bool operator < (const Node &​b)const{
 + return v<b.v;
 + }
 + Node(int ql=0,int qr=0,int x=0){
 + this->​ql=ql,​this->​qr=qr,​this->​x=x;​
 + nxt=query(ql,​qr,​a[x]);​
 + v=a[x]^a[nxt];​
 + }
 +};
 +priority_queue<​Node>​ q;
 +int main()
 +{
 + int n=read_int(),​k=read_int();​
 + Insert(root[0],​root[0],​0,​0,​MAXM-1);​
 + _rep(i,​1,​n)a[i]=read_LL()^a[i-1],​Insert(root[i],​root[i-1],​i,​a[i],​MAXM-1);​
 + _rep(i,​1,​n)q.push(Node(0,​i-1,​i));​
 + LL ans=0;
 + while(k--){
 + Node temp=q.top();​q.pop();​
 + ans+=temp.v;​
 + if(temp.nxt>​temp.ql)q.push(Node(temp.ql,​temp.nxt-1,​temp.x));​
 + if(temp.nxt<​temp.qr)q.push(Node(temp.nxt+1,​temp.qr,​temp.x));​
 + }
 + enter(ans);​
 + return 0;
 +}
 +</​code>​
 +</​hidden>​
 +
 +==== 习题三 ====
 +
 +[[https://​www.luogu.com.cn/​problem/​P5795|洛谷p5795]]
 +
 +=== 题意 ===
 +
 +给定一个长度为 $n$ 的序列 $X$ 和长度为 $m$ 的序列 $Y$,定义矩阵元素 $A_{i,​j}=X_i\oplus Y_j$,接下来 $q$ 个询问。
 +
 +每次询问 $A_{i,​j}(l_1\le i\le r_1,l_2\le j\le r_2)$ 第 $k$ 大。数据保证 $n\le 1000,m\le 300000,q\le 500$。
 +
 +=== 题解 ===
 +
 +对序列 $Y$ 建字典树,差分维护区间结点个数。每次询问时同时对序列 $X_i(l_1\le r_1)$ 跳字典树。
 +
 +考虑按位贪心,先查询异或结果为 $1$ 的结点个数,根据结点个数考虑跳边方向。时间复杂度 $O((nq+m)\log v)$。
 +
 +<hidden 查看代码>​
 +<code cpp>
 +const int MAXN=1e3+5,​MAXM=3e5+5,​MAXL=31;​
 +struct Node{
 + int ch[2],sz;
 +}node[MAXM*40];​
 +int root[MAXM],​node_cnt;​
 +void Insert(int &k,int p,int v){
 + int pos=k=++node_cnt;​
 + for(int i=MAXL-1;​~i;​i--){
 + int dir=(v>>​i)&​1;​
 + node[pos].ch[!dir]=node[p].ch[!dir];​
 + node[pos].ch[dir]=++node_cnt;​
 + pos=node[pos].ch[dir];​
 + p=node[p].ch[dir];​
 + node[pos].sz=node[p].sz+1;​
 + }
 +}
 +int x[MAXN],​y[MAXM],​cur_pos[MAXN][2];​
 +int query(int l1,int r1,int l2,int r2,int rk){
 + int ans=0;
 + _rep(i,​l1,​r1){
 + cur_pos[i][0]=root[r2];​
 + cur_pos[i][1]=root[l2-1];​
 + }
 + for(int i=MAXL-1;​~i;​i--){
 + int cnt=0;
 + _rep(j,​l1,​r1){
 + int dir=((x[j]>>​i)&​1)^1;​
 + cnt+=node[node[cur_pos[j][0]].ch[dir]].sz-node[node[cur_pos[j][1]].ch[dir]].sz;​
 + }
 + int flag=cnt>​=rk;​
 + if(flag)
 + ans|=1<<​i;​
 + else
 + rk-=cnt;
 + _rep(j,​l1,​r1){
 + int dir=((x[j]>>​i)&​1)^flag;​
 + cur_pos[j][0]=node[cur_pos[j][0]].ch[dir];​
 + cur_pos[j][1]=node[cur_pos[j][1]].ch[dir];​
 + }
 + }
 + return ans;
 +}
 +int main()
 +{
 + int n=read_int(),​m=read_int();​
 + _rep(i,​1,​n)x[i]=read_int();​
 + _rep(i,​1,​m){
 + y[i]=read_int();​
 + Insert(root[i],​root[i-1],​y[i]);​
 + }
 + int q=read_int();​
 + while(q--){
 + int l1=read_int(),​r1=read_int(),​l2=read_int(),​r2=read_int();​
 + enter(query(l1,​r1,​l2,​r2,​read_int()));​
 + }
  return 0;  return 0;
 } }
 </​code>​ </​code>​
 </​hidden>​ </​hidden>​
2020-2021/teams/legal_string/jxm2001/可持久化数据结构_3.1597746419.txt.gz · 最后更改: 2020/08/18 18:26 由 jxm2001