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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

bzoj4025: 二分图

發(fā)布時間:2024/8/26 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj4025: 二分图 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這題想不出來。

不浪費時間了。

以后找時間填。

?--------------------update---------------

就是判奇環(huán)咯

然而LCT我搞不出來。。

是因為對于當前的最大生成樹,新時間加入的邊可能是比前面最大生成樹里最小邊要大,然后就要找到最大生成樹里最小的邊。。這樣要化邊為點我萎了還是寫不出來你們?nèi)?吧

?

#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<map> using namespace std;struct node {int x,y; }a[210000];struct heap_st {int st,ed,id;friend bool operator>(heap_st n1,heap_st n2){return n1.st>n2.st;} };priority_queue<heap_st,vector<heap_st>,greater<heap_st> >A; struct heap_ed {int ed,id;friend bool operator>(heap_ed n1,heap_ed n2){return n1.ed>n2.ed;} };priority_queue<heap_ed,vector<heap_ed>,greater<heap_ed> >B; struct heap_mt {int ed,id;friend bool operator>(heap_mt n1,heap_mt n2){return n1.ed<n2.ed;} };priority_queue<heap_mt,vector<heap_mt>,greater<heap_mt> >C;//---------edge&&heap---------------struct LCT {int f,c,son[2];bool fz; }tr[210000]; void yu(int n){for(int i=1;i<=n;i++)tr[i].c=1,tr[i].fz=false;} void update(int x) {int lc=tr[x].son[0],rc=tr[x].son[1];tr[x].c=tr[lc].c+tr[rc].c+1; } void reverse(int x) {tr[x].fz=false;swap(tr[x].son[0],tr[x].son[1]);int lc=tr[x].son[0],rc=tr[x].son[1];tr[lc].fz=1-tr[lc].fz;tr[rc].fz=1-tr[rc].fz; } void rotate(int x,int w) {int f=tr[x].f,ff=tr[f].f;int R,r;R=f;r=tr[x].son[w];tr[R].son[1-w]=r;if(r!=0)tr[r].f=R;R=ff;r=x;if(tr[R].son[0]==f)tr[R].son[0]=r;else if(tr[R].son[1]==f)tr[R].son[1]=r;tr[r].f=R;R=x;r=f;tr[R].son[w]=r;tr[r].f=R;update(f);update(x); } bool isroot(int x) {if(tr[x].f!=0&&(tr[tr[x].f].son[0]==x||tr[tr[x].f].son[1]==x))return false;return true; } int tmp[210000]; void splay(int x,int rt) {int s=0,i=x;while(isroot(i)==false){tmp[++s]=i;i=tr[i].f;} tmp[++s]=i;while(s!=0){i=tmp[s];s--;if(tr[i].fz==true)reverse(i);}while(isroot(x)==false){int f=tr[x].f,ff=tr[f].f;if(isroot(f)==true){if(x==tr[f].son[0])rotate(x,1);else rotate(x,0);}else{if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);}else if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);}else if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);}else if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);}}} }//splayvoid access(int x) {int y=0;while(x!=0){splay(x,0);tr[x].son[1]=y;if(y!=0)tr[y].f=x;update(x);y=x;x=tr[x].f;} } void makeroot(int x) {access(x);splay(x,0);tr[x].fz=1-tr[x].fz; } void Link(int x,int y) {makeroot(x);tr[x].f=y;access(x); } void Cut(int x,int y) {makeroot(x);access(y);splay(y,0);tr[tr[y].son[0]].f=0;tr[y].son[0]=0;update(y); } int findroot(int x) {access(x);splay(x,0);while(tr[x].son[0]!=0)x=tr[x].son[0];return x; }//simpleint getdis(int x,int y) {makeroot(x);access(y);splay(y,0);int ret=1;while(y!=x){y=tr[y].son[0];ret+=tr[tr[y].son[1]].c+1;}return ret; }//-------------------LCT------------------- bool intree[210000];//該邊是否在樹上 int main() {freopen("data.in","r",stdin);freopen("data.out","w",stdout);int n,m,T;scanf("%d%d%d",&n,&m,&T);yu(n);int st,ed;for(int i=1;i<=m;i++){scanf("%d%d",&a[i].x,&a[i].y);scanf("%d%d",&st,&ed);st++;ed++;if(st>=ed){i--;m--;continue;}heap_st tt;tt.st=st, tt.ed=ed, tt.id=i;A.push(tt);}int tim=0;memset(intree,false,sizeof(intree));for(int t=1;t<=T;t++){while(B.empty()==false){heap_ed h=B.top();if(h.ed==t){B.pop();int k=h.id;if(intree[k]==true){intree[k]=false;Cut(a[k].x,a[k].y);}}else break;}//----------結(jié)束時間到,刪除樹上邊,非樹上邊可以直接無視,更新-------while(A.empty()==false){heap_st h=A.top();if(h.st==t){A.pop();heap_ed tt;tt.ed=h.ed, tt.id=h.id;B.push(tt);heap_mt uu;uu.ed=h.ed, uu.id=h.id;C.push(uu);}else break;}//----------起始時間到,將邊入堆---------- while(C.empty()==false){heap_mt h=C.top();C.pop();if(h.ed<=t)break;int k=h.id;int x=a[k].x,y=a[k].y;if(x==y){tim=max(tim,h.ed-1);continue;}if(findroot(x)!=findroot(y)){intree[k]=true;Link(x,y);}else{if(getdis(x,y)%2==1)tim=max(tim,h.ed-1);}}//----------將樹邊連滿&&判奇環(huán)---------------- if(t<=tim)printf("No\n");else printf("Yes\n");}return 0; } lj的WAcode

?

--------------------然而cdq+帶權(quán)并查集搞出來了。。。-----------------------

感覺這個不算cdq分治,只是普通分治而已-_-! upd:這個東西其實叫線段樹分治。。。。。

具體怎么做呢,就是類似線段樹一樣把每一時間段下放影響,這樣可以保證對于當前這一段包含的邊都是沒消失的,然后假如遇到奇環(huán)就把當前區(qū)間全部設(shè)為false就行。

?

dis可以直接用異或代替,因為只是要判奇偶性,路徑不用壓縮,修改需要父親,分治可以保證平衡。

?

#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std;int fa[210000],d[210000]; int findfa(int x) {while(x!=fa[x])x=fa[x];return x; } int getdis(int x) {int dis=0;while(x!=fa[x])dis^=d[x],x=fa[x];return dis; }//---------union-find sets------------- int top,sta[410000];bool v[410000]; int rak[210000]; void Link(int x,int y,int dis) {if(rak[x]>rak[y]){top++;sta[top]=y,v[top]=true;fa[y]=x,d[y]=dis;}else if(rak[x]<rak[y]){top++;sta[top]=x,v[top]=true;fa[x]=y,d[x]=dis;}else{rak[x]++;top++;sta[top]=y,v[top]=false;fa[y]=x,d[y]=dis;} } void Cut(int now) {while(now!=top){int k=sta[top];top--;if(v[top+1]==false)rak[fa[k]]--;fa[k]=k, d[k]=0;} }//------------------玄學-------------------------------- struct edge{int x,y,st,ed;}; bool as[210000]; void cdq(int l,int r,vector<edge> hh) {int mid=(l+r)/2;vector<edge> ll,rr;int len=hh.size(),now=top;for(int i=0;i<len;i++){edge e=hh[i];if(e.st==l&&e.ed==r){int x=e.x,y=e.y;int fx=findfa(x),fy=findfa(y);int dis=getdis(x)^getdis(y)^1;if(fx!=fy)Link(fx,fy,dis);else if((dis&1)>0){for(int i=l;i<=r;i++)as[i]=false;Cut(now);return ;}}else if(e.ed<=mid) ll.push_back(e);else if(mid+1<=e.st)rr.push_back(e);else{edge lc,rc;lc=rc=e;lc.ed=mid;rc.st=mid+1;ll.push_back(lc);rr.push_back(rc);}}if(l==r)as[l]=true;else cdq(l,mid,ll), cdq(mid+1,r,rr);Cut(now); }vector<edge> S; int main() {int n,m,T;scanf("%d%d%d",&n,&m,&T);for(int i=1;i<=m;i++){int x,y,st,ed;scanf("%d%d%d%d",&x,&y,&st,&ed);if(st>=ed)continue;st++; S.push_back((edge){x,y,st,ed});}for(int i=1;i<=n;i++)fa[i]=i;memset(d,0,sizeof(d));memset(rak,0,sizeof(rak));top=0;cdq(1,T,S);for(int i=1;i<=T;i++)if(as[i]==true)printf("Yes\n");else printf("No\n");return 0; } 現(xiàn)在已經(jīng)看不懂的代碼

?

-------------------------------再一次upd----------------------------------------

學會了線段樹分治就是傻子題了,只要上并查集判奇環(huán)即可

?

#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std;struct edge{int x,y;}e[210000]; struct node {int l,r,lc,rc;vector<int>id,u; }tr[210000];int trlen; void bt(int l,int r) {int now=++trlen;tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;if(l<r){int mid=(l+r)/2;tr[now].lc=trlen+1;bt(l,mid);tr[now].rc=trlen+1;bt(mid+1,r);} } void insert(int now,int l,int r,int p) {if(tr[now].l==l&&tr[now].r==r){tr[now].id.push_back(p);return ;}int lc=tr[now].lc,rc=tr[now].rc;int mid=(tr[now].l+tr[now].r)/2;if(r<=mid) insert(lc,l,r,p);else if(mid+1<=l)insert(rc,l,r,p);else insert(lc,l,mid,p),insert(rc,mid+1,r,p); }//---------------------------------------init----------------------------------------------------int fa[210000]; const int ot=101000; int findfa(int x) {if(fa[x]<0)return x;return findfa(fa[x]); } void merge(int now,bool &bk,int x,int y) {int fx1=findfa(x),fy2=findfa(y+ot);if(fx1!=fy2){if(fa[fx1]>fa[fy2]){tr[now].u.push_back(fx1);fa[fy2]+=fa[fx1];fa[fx1]=fy2;}else{tr[now].u.push_back(fy2);fa[fx1]+=fa[fy2];fa[fy2]=fx1;}}int fy1=findfa(y),fx2=findfa(x+ot);if(fx2!=fy1){if(fa[fx2]>fa[fy1]){tr[now].u.push_back(fx2);fa[fy1]+=fa[fx2];fa[fx2]=fy1;}else{tr[now].u.push_back(fy1);fa[fx2]+=fa[fy1];fa[fy1]=fx2;}}if(findfa(fx1)==findfa(fx2)||findfa(fy1)==findfa(fy2))bk=false; } struct Answer{int l,r;bool b;}as[110000];int tp; void dfs(int now) {bool bk=true;for(int i=0;i<tr[now].id.size();i++)merge(now,bk,e[tr[now].id[i]].x,e[tr[now].id[i]].y);if(bk==false){as[++tp].l=tr[now].l,as[tp].r=tr[now].r,as[tp].b=false; }else{if(tr[now].l==tr[now].r)as[++tp].l=as[tp].r=tr[now].l,as[tp].b=true;else{dfs(tr[now].lc);dfs(tr[now].rc);}}for(int i=0;i<tr[now].u.size();i++)fa[tr[now].u[i]]=-1; }int main() {freopen("a.in","r",stdin);freopen("a.out","w",stdout);int n,m,T,st,ed;scanf("%d%d%d",&n,&m,&T);trlen=0;bt(1,T);for(int i=1;i<=m;i++){scanf("%d%d%d%d",&e[i].x,&e[i].y,&st,&ed);if(st>=ed){i--,m--;continue;}insert(1,st+1,ed,i);}memset(fa,-1,sizeof(fa));tp=0;dfs(1);for(int i=1;i<=tp;i++)for(int j=as[i].l;j<=as[i].r;j++)if(as[i].b)printf("Yes\n");else printf("No\n");return 0; }

?

轉(zhuǎn)載于:https://www.cnblogs.com/AKCqhzdy/p/8516221.html

總結(jié)

以上是生活随笔為你收集整理的bzoj4025: 二分图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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