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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jzoj4739-[雅礼联考GDOI2017模拟9.2]Ztxz16学图论【LCT,树状数组】

發(fā)布時(shí)間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj4739-[雅礼联考GDOI2017模拟9.2]Ztxz16学图论【LCT,树状数组】 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

正題

題目鏈接:https://gmoj.net/senior/#main/show/4739


題目大意

nnn個(gè)點(diǎn)mmm條邊的一張圖,qqq次詢問一個(gè)區(qū)間的邊可以形成多少連通塊。


解題思路

詢問按照右端點(diǎn)排序,然后邊權(quán)就是編號(hào),這樣詢問最大生成樹后判斷有多少個(gè)邊權(quán)大于lll即可。用LCTLCTLCT維護(hù)這個(gè)最大生成樹然后用樹狀數(shù)組記錄每條邊的權(quán)值。

時(shí)間復(fù)雜度O(nlog?n)O(n\log n)O(nlogn)

當(dāng)然也可以莫隊(duì)做,維護(hù)到每個(gè)塊時(shí)的情況,然后右指針右移,左指針右移是暴力還原到每個(gè)塊的末尾即可。

時(shí)間復(fù)雜度O(nn)O(n\sqrt n)O(nn?)

當(dāng)然這里是用LCTLCTLCT做的。


codecodecode

#include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define lowbit(x) (x&-x) using namespace std; const int N=4e5+10; struct node{int x,y,id; }a[N],p[N]; int n,m,q,val[N],sum[N],ans[N],fa[N]; struct Link_Cut_Tree{int t[N][2],fa[N];bool r[N];stack<int>s;bool Nroot(int x){return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);}bool Direct(int x){return t[fa[x]][1]==x;}void PushUp(int x){sum[x]=min(val[x],min(sum[t[x][0]],sum[t[x][1]]));return;}void Rev(int x){swap(t[x][0],t[x][1]);r[x]^=1;return;}void PushDown(int x){if(!r[x])return;Rev(t[x][0]);Rev(t[x][1]);r[x]^=1;return;}void Rotate(int x){int y=fa[x],z=fa[fa[x]];int xs=Direct(x),ys=Direct(y);int w=t[x][!xs];t[y][xs]=0;t[y][xs]=w;t[x][!xs]=y;if(Nroot(y))t[z][ys]=x;if(w)fa[w]=y;fa[y]=x;fa[x]=z;PushUp(y);PushUp(x);return;}void Splay(int x){s.push(x);while(Nroot(s.top())) s.push(fa[s.top()]);while(!s.empty()) PushDown(s.top()),s.pop();while(Nroot(x)){int y=fa[x];if(!Nroot(y))Rotate(x);else if(Direct(x)==Direct(y))Rotate(y),Rotate(x);else Rotate(x),Rotate(x); }return;}void Access(int x){for(int y=0;x;x=fa[y=x])Splay(x),t[x][1]=y,PushUp(x);return;}void MakeRoot(int x){Access(x);Splay(x);Rev(x);return;}int Split(int x,int y){MakeRoot(x);Access(y);Splay(y);return sum[y];}void Link(int x,int y){MakeRoot(x);fa[x]=y;Access(x);return;}void Cut(int x,int y){MakeRoot(y);Access(x);Splay(x);fa[t[x][0]]=0;t[x][0]=0;PushUp(x);return;} }LCT; struct Tree_Array{int t[N];void Change(int x,int val){while(x<=m){t[x]+=val;x+=lowbit(x);}return;}int Ask(int x){int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans;} }T; int find(int x) {return (fa[x]==x)?x:(fa[x]=find(fa[x]));} bool cmp(node x,node y) {return x.y<y.y;} int main() {scanf("%d%d%d",&n,&m,&q);memset(val,0x3f,sizeof(val));memset(sum,0x3f,sizeof(sum));for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++){scanf("%d%d",&a[i].x,&a[i].y);val[i+n]=sum[i+n]=i;}for(int i=1;i<=q;i++)scanf("%d%d",&p[i].x,&p[i].y),p[i].id=i;sort(p+1,p+1+q,cmp);int z=0;for(int i=1;i<=q;i++){while(z<m&&z<p[i].y){z++;int x=a[z].x,y=a[z].y;if(x==y)continue;int X=find(x),Y=find(y);if(X==Y){int w=LCT.Split(x,y);LCT.Cut(w+n,a[w].x);LCT.Cut(w+n,a[w].y);T.Change(w,-1);}else fa[X]=Y;LCT.Link(x,z+n);LCT.Link(y,z+n);T.Change(z,1);}ans[p[i].id]=n-(T.Ask(p[i].y)-T.Ask(p[i].x-1));}for(int i=1;i<=q;i++)printf("%d\n",ans[i]); }

總結(jié)

以上是生活随笔為你收集整理的jzoj4739-[雅礼联考GDOI2017模拟9.2]Ztxz16学图论【LCT,树状数组】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。