日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

3237: [Ahoi2013]连通图 线段树分治

發布時間:2025/3/14 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3237: [Ahoi2013]连通图 线段树分治 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題解:

cf765f

cf671e

bzoj4184

bzoj4552

線段樹分治裸題

還是介紹一下線段樹分治

這個東西其實挺簡單但也挺有用的

可以把刪除+插入操作變成只有插入(倒著就是刪除)

像這一道題,我們對時間點建立線段樹

對一段區間共同有的元素依次加入到線段樹中(開個隊列維護一下)

發現這樣是只有nlogn個點

另外這個標記顯然是可以標記永久化的

apio t1是這個所以就學習了一下

為了練習一下可持久化并查集于是我就寫了

然后主席樹造成了它一定會mle。。nlognlog(nlogn)

其實只用帶撤銷的并查集就可以了

#include <bits/stdc++.h> using namespace std; const int N=4e7+10; const int N2=3e5+10; struct re{int x,y; }a[N2]; int cnt,now,n,m,k; int ls[N],rs[N],data[N]; int ph[N2*4],pt[N2*4],count2[N2],f[N2]; bool ft[N2]; vector<int> ve[N2*4]; #define mid (ph[x]+pt[x])/2 void change(int last,int &now,int h,int t,int goal,int goal2) {now=++cnt;if (h==t){ data[now]=goal2;return;}ls[now]=ls[last];rs[now]=rs[last];int mid2=(h+t)/2;if (goal<=mid2) change(ls[last],ls[now],h,mid2,goal,goal2);else change(rs[last],rs[now],mid2+1,t,goal,goal2); } int query(int x,int h,int t,int goal) {if (h==t) return(data[x]);int mid2=(h+t)/2;if (goal<=mid2) return(query(ls[x],h,mid2,goal));else return(query(rs[x],mid2+1,t,goal)); } void build(int x,int h,int t) {ph[x]=h; pt[x]=t;if (h==t) return;build(x*2,h,mid); build(x*2+1,mid+1,t); } void insert(int x,int h,int t,int goal) {if (h<=ph[x]&&pt[x]<=t){ ve[x].push_back(goal);return;}if (h<=mid) insert(x*2,h,t,goal);if (mid<t) insert(x*2+1,h,t,goal); } int find(int root,int x) {int y=query(root,1,N,x);if (y==x) return(x);else return(find(root,y)); } void dfs(int x,int h,int t,int ans) {stack<re> s;int now1=now;int len=ve[x].size();for (int i=0;i<len;i++){int x1=a[ve[x][i]].x,x2=a[ve[x][i]].y;int x11=find(now,x1),x22=find(now,x2);if (x11!=x22){if (count2[x11]>count2[x22]) swap(x11,x22);change(now,now,1,N,x11,x22);s.push(re{x22,count2[x22]});count2[x22]+=count2[x11];ans++;}}if (h==t){if (ans==n-1) ft[h]=1; else ft[h]=0;} else{dfs(x*2,h,(h+t)/2,ans); dfs(x*2+1,(h+t)/2+1,t,ans);}while (!s.empty()){re x=s.top(); s.pop();count2[x.x]=x.y;}now=now1; } int main() {freopen("3237.in","r",stdin);freopen("3237.out","w",stdout);cin>>n>>m;for (int i=1;i<=m;i++){cin>>a[i].x>>a[i].y;}cin>>k;for (int i=1;i<=n;i++) f[i]=1;for (int i=1;i<=n;i++){change(now,now,1,N,i,i);count2[i]=1;}build(1,1,k);for (int i=1;i<=k;i++){int nown,x;cin>>nown;for (int j=1;j<=nown;j++){cin>>x;if (i-1>=f[x]){insert(1,f[x],i-1,x);}f[x]=i+1;}}for (int i=1;i<=m;i++)if (f[i]<=k)insert(1,f[i],k,i);dfs(1,1,k,0);for (int i=1;i<=k;i++)if (ft[i]==1) cout<<"Connected"<<endl;else cout<<"Disconnected"<<endl;return 0; }

?這個是正確的

#include <bits/stdc++.h>using namespace std;const int N=4e7+10;const int N2=3e5+10; #define rint register int struct re{int x,y,z;}a[N2]; char ss[1<<24],*A=ss,*B=ss; inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;} template<class T>void read(T&x){rint f=1,c;while(c=gc(),c<48||57<c)if(c=='-')f=-1;x=c^48;while(c=gc(),47<c&&c<58)x=(x<<3)+(x<<1)+(c^48);x*=f; } int cnt,now,n,m,k;int ph[N2*4],pt[N2*4],fa[N2],count2[N2],f[N2];bool ft[N2];vector<int> ve[N2*4];#define mid (ph[x]+pt[x])/2void build(int x,int h,int t){ph[x]=h; pt[x]=t;if (h==t) return;build(x*2,h,mid); build(x*2+1,mid+1,t);}void insert(int x,int h,int t,int goal){if (h<=ph[x]&&pt[x]<=t){ ve[x].push_back(goal);return;}if (h<=mid) insert(x*2,h,t,goal);if (mid<t) insert(x*2+1,h,t,goal);}int find(int x){int y=fa[x];if (y==x) return(x);else return(find(y));}void dfs(int x,int h,int t,int ans){stack<re> s;int now1=now;int len=ve[x].size();for (int i=0;i<len;i++){int x1=a[ve[x][i]].x,x2=a[ve[x][i]].y;int x11=find(x1),x22=find(x2);if (x11!=x22){if (count2[x11]>count2[x22]) swap(x11,x22);fa[x11]=x22;s.push(re{x22,count2[x22],x11});count2[x22]+=count2[x11];ans++;}}if (h==t){if (ans==n-1) ft[h]=1; else ft[h]=0;} else{dfs(x*2,h,(h+t)/2,ans); dfs(x*2+1,(h+t)/2+1,t,ans);}while (!s.empty()){re x=s.top(); s.pop();count2[x.x]=x.y;fa[x.z]=x.z;}now=now1;}int main(){freopen("3237.in","r",stdin);freopen("3237.out","w",stdout);read(n); read(m); for (int i=1;i<=m;i++){read(a[i].x); read(a[i].y);}read(k);for (int i=1;i<=n;i++) f[i]=1;for (int i=1;i<=n;i++){fa[i]=i;count2[i]=1;}build(1,1,k);for (int i=1;i<=k;i++){int nown,x;read(nown);for (int j=1;j<=nown;j++){read(x);if (i-1>=f[x]){insert(1,f[x],i-1,x);}f[x]=i+1;}}for (int i=1;i<=m;i++)if (f[i]<=k)insert(1,f[i],k,i);dfs(1,1,k,0);for (int i=1;i<=k;i++)if (ft[i]==1) puts("Connected");else puts("Disconnected");return 0;}

?

轉載于:https://www.cnblogs.com/yinwuxiao/p/9038629.html

總結

以上是生活随笔為你收集整理的3237: [Ahoi2013]连通图 线段树分治的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。