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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

bzoj4383(拓扑排序)

發布時間:2025/3/19 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj4383(拓扑排序) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

給定一個長度為n的正整數序列a,每個數都在1到10^9范圍內,告訴你其中s個數,并給出m條信息,每條信息包含三個數l,r,k以及接下來k個正整數,表示a[l],a[l+1],...,a[r-1],a[r]里這k個數中的任意一個都比任意一個剩下的r-l+1-k個數大(嚴格大于,即沒有等號)。請任意構造出一組滿足條件的方案,或者判斷無解。

Solution

這個模型有點像差分約束系統,但是建圖復雜度過高。

考慮到每次一個區間內的k個數將整段序列劃分為k+1個區間,所以我們考慮用線段樹優化這個過程,每次建一個s點和這k個點連邊,再和剩下的數所對應的區間連邊,這樣就保證了我們建圖的復雜度。

然后題目中給的數域是1-1e9,有兩種方法,一種是從極小向大里跑,另一種是從極大往小里跑。

如果是前一種,那么我的轉移順序必須為從小到大,回顧我們的連邊,發現需要從一堆區間向S走,但是這一堆區間需要下面的節點轉移而來,所以我們在線段樹上連邊的方式為從下往上連。

后一種反之。

Code

#include<iostream> #include<cstdio> #include<queue> #include<cstring> #define N 400002 #define M 4000003 using namespace std; queue<int>q; int head[N],tot,du[N],ji[N],anti_ji[N],top,rs[N],ls[N],s,n,m,pos,ss,x,a[N],l,r,k,num[N],tag; struct node{int n,to,l; }e[M]; inline void add(int u,int v,int l){e[++tot].n=head[u];e[tot].to=v;e[tot].l=l;du[v]++;head[u]=tot; } void build(int cnt,int l,int r){if(l==r){ji[l]=cnt;anti_ji[cnt]=l;return;}int mid=(l+r)>>1;ls[cnt]=++top;rs[cnt]=++top;add(ls[cnt],cnt,0);add(rs[cnt],cnt,0);build(ls[cnt],l,mid);build(rs[cnt],mid+1,r); } void query(int cnt,int l,int r,int L,int R){if(l>=L&&r<=R){add(cnt,s,0);return;}int mid=(l+r)>>1;if(mid>=L)query(ls[cnt],l,mid,L,R);if(mid<R)query(rs[cnt],mid+1,r,L,R); } int main(){top=1;scanf("%d%d%d",&n,&ss,&m);for(int i=1;i<=ss;++i)scanf("%d%d",&pos,&x),a[pos]=x;build(1,1,n);for(int i=1;i<=m;++i){scanf("%d%d%d",&l,&r,&k);int p=l;s=++top;for(int j=1;j<=k;++j){scanf("%d",&x);add(s,ji[x],1);if(x>p)query(1,1,n,p,x-1);p=x+1;}if(p<=r)query(1,1,n,p,r);}for(int i=1;i<=top;++i){if(!du[i])q.push(i),num[i]=1;if(a[anti_ji[i]])num[i]=a[anti_ji[i]];}while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i;i=e[i].n){int v=e[i].to,x=num[u]+e[i].l;if(!--du[v])q.push(v);if(!a[anti_ji[v]]){num[v]=max(num[v],x);}else{num[v]=a[anti_ji[v]];if(a[anti_ji[v]]<x)tag=1;}}}for(int i=1;i<=top;++i)if(du[i])tag=1;for(int i=1;i<=n;++i)if(num[ji[i]]>1e9||!num[ji[i]])tag=1;if(tag){printf("NIE\n");return 0;}printf("TAK\n");for(int i=1;i<=n;++i)printf("%d ",num[ji[i]]);return 0; }

Code2

#include<iostream> #include<cstdio> #include<queue> #define N 400002 #define M 4000003 using namespace std; queue<int>q; int head[N],tot,du[N],ji[N],anti_ji[N],top,rs[N],ls[N],s,n,m,pos,ss,x,a[N],l,r,k,num[N],tag; struct node{int n,to,l; }e[M]; inline void add(int u,int v,int l){e[++tot].n=head[u];e[tot].to=v;e[tot].l=l;du[v]++;head[u]=tot; } void build(int cnt,int l,int r){if(l==r){ji[l]=cnt;anti_ji[cnt]=l;return;}int mid=(l+r)>>1;ls[cnt]=++top;rs[cnt]=++top;add(cnt,ls[cnt],0);add(cnt,rs[cnt,0);build(ls[cnt],l,mid);build(rs[cnt],mid+1,r); } void query(int cnt,int l,int r,int L,int R){if(l>=L&&r<=R){add(s,cnt,0);return;}int mid=(l+r)>>1;if(mid>=L)query(ls[cnt],l,mid,L,R);if(mid<R)query(rs[cnt],mid+1,r,L,R); } int main(){top=1;scanf("%d%d%d",&n,&ss,&m);for(int i=1;i<=ss;++i)scanf("%d%d",&pos,&x),a[pos]=x;build(1,1,n);for(int i=1;i<=m;++i){scanf("%d%d%d",&l,&r,&k);int p=l;s=++top;for(int j=1;j<=k;++j){scanf("%d",&x);add(ji[x],s,1);if(x>p)query(1,1,n,p,x-1);p=x+1;}if(p<=r)query(1,1,n,p,r);}for(int i=1;i<=top;++i){if(!du[i])q.push(i);num[i]=1e9;}while(!q.empty()){int u=q.front();q.pop();if(anti_ji[u]&&!num[u])num[u]=1e9;for(int i=head[u];i;i=e[i].n){int v=e[i].to,x=num[u]-e[i].l;if(!--du[v])q.push(v);if(!a[anti_ji[v]]){num[v]=min(num[v],x);}else{num[v]=a[anti_ji[v]];if(a[anti_ji[v]]>x)tag=1;}}}for(int i=1;i<=top;++i)if(du[i])tag=1;if(tag){printf("NIE\n");return 0;}printf("TAK\n");for(int i=1;i<=n;++i)printf("%d ",num[ji[i]]);return 0; }

?

轉載于:https://www.cnblogs.com/ZH-comld/p/9828177.html

總結

以上是生活随笔為你收集整理的bzoj4383(拓扑排序)的全部內容,希望文章能夠幫你解決所遇到的問題。

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