這個題目就是誤導你的,據說zky用了rope。。所以苦於用並查集強行持久的似乎不太好做
這個題可以根據並查集的原理只加啟發式合併優化
這樣就可以常數巨大、空間巨大的nlogn了
啟發式合併的過程 對於數值上來說 就是乙個fu陣列賦值為另乙個的fu陣列,所以相當於單點修改
sz單點加
撤銷過程相當於回到前幾個詢問
很像主席樹啊,還是單點修改,,就比較好做了
注:1、複製貼上注意修改
2、注意查詢時用上一棵樹
3、注意開點的情況,,已經有了就不能再建了
碼:
#include#includeusing namespace std;
#define n 100005
int ch[(n<<2)*60][2],fu[(n<<2)*60],sz[(n<<2)*60],tot,op,a,b,c,cz,rt[n],n,m,i,j,x,y;
void jian(int o,int l,int r)
int mid=(l+r)>>1;
ch[o][0]=++tot;
ch[o][1]=++tot;
jian(ch[o][0],l,mid);
jian(ch[o][1],mid+1,r);
}void gai(int o,int l,int r,int last)
if(op==2)
if(op==3)
if(op==4)
return;
} int mid=(l+r)>>1;
if(a<=mid)
else }
int main()
int c1=c;
c=y;
a=0;
while(a!=c)
int c2=c;
int cc1,cc2;
op=3;
a=c1;
gai(rt[i-1],1,n,rt[i-1]);
cc1=c;
a=c2;
gai(rt[i-1],1,n,rt[i-1]);
cc2=c;
if(cc1>cc2)swap(cc1,cc2);
op=1;
a=c1;
c=c2;
gai(rt[i],1,n,rt[i-1]);
op=2;
a=c2;
c=cc1;
gai(rt[i],1,n,rt[i-1]); }
if(cz==2)
if(cz==3)
int c1=c;
c=y;
a=0;
while(a!=c)
int c2=c;
if(c1==c2)
else printf("0\n");
} }
}
可持久化並查集
n個集合 m個操作 1 a b 合併a,b所在集合 2 k 回到第k次操作之後的狀態 查詢算作操作 3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出0 所給的a,b,k均經過加密,加密方法為x x xor lastans,lastans是上一次的輸出答案 並查集實質是乙個陣列,可持久化並查...
可持久化並查集
可持久化陣列 可持久化陣列是一種可以回退,訪問之前版本的陣列 是一些其他可持久化資料結構的基石 例如可持久化並查集 與普通並查集不同的是 這裡用到了 按秩合併新增鏈結描述 include const int n 2e5 7 int rootfa n rootdep n cnt,tot struct ...
可持久化並查集
點此看題 並查集最重要的就是fafa fa陣列,我們可以拿主席樹來維護這個fafa fa,並且每次改點只需要改乙個,為保證時間複雜度我們再維護乙個dep depde p來做啟發式合併,這就變成了乙個單點修改,單點查詢的主席樹了。include include using namespace std ...