还以为是差分约束,原来拓扑排序也能解决这样的问题=。=
类似差分约束的建图方式,我们把大小关系看做有向边。这样一来图上是不允许存在环的,于是我们可以做拓扑排序。然后问题来了,边数非常大,根本建不出图来=。=
不过我们有一个套路的做法,为每个区间配一个虚点,然后连边时先连到虚点再连到各个目标点。然后问题又来了,这样连边其实是$O(len^2)$的,$len$为区间长度,如果有个很大的区间这就萎了=。=
那什么东西解决区间问题好用呢?线段树— —我们用线段树优化建图,每次直接从虚点连到区间上,这样最多会连出来$k+klog$ $n$条边(点向虚点连的+虚点向区间连的),然后线段树内还有$4*n$条边,总共大概有不到570万条边,还可以接受。再之后做拓扑排序就可以了
注意数值的最大值和连边时的边权
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=600005,M=3400005,maxx=1e9; 6 int num[N],ls[N],rs[N]; 7 int vis[N],ins[N],dp[N],mem[N],que[N]; 8 int p[N],noww[M],goal[M],val[M],deg[N]; 9 int n,s,m,l,r,k,f,b,rd,t1,t2,t3,tn,cnt,tot,pos; 10 void GG(){printf("NIE"),exit(0);} 11 void link(int f,int t,int v) 12 { 13 noww[++cnt]=p[f],p[f]=cnt; 14 goal[cnt]=t,val[cnt]=v,deg[t]++; 15 } 16 void Create(int nde,int l,int r) 17 { 18 if(l==r) num[l]=nde; 19 else 20 { 21 int mid=(l+r)/2; 22 ls[nde]=++tot,rs[nde]=++tot; 23 link(nde,ls[nde],0),link(nde,rs[nde],0); 24 Create(ls[nde],l,mid),Create(rs[nde],mid+1,r); 25 } 26 } 27 void Change(int nde,int l,int r,int nl,int nr,int task) 28 { 29 if(l>nr||r<nl) 30 return ; 31 else if(l>=nl&&r<=nr) 32 link(task,nde,1); 33 else 34 { 35 int mid=(l+r)/2; 36 Change(ls[nde],l,mid,nl,nr,task); 37 Change(rs[nde],mid+1,r,nl,nr,task); 38 } 39 } 40 bool DFS(int nde) 41 { 42 vis[nde]=ins[nde]=true; 43 for(int i=p[nde];i;i=noww[i]) 44 { 45 if(ins[goal[i]]) return false; 46 if(!vis[goal[i]]&&!DFS(goal[i])) return false; 47 } 48 ins[nde]=false; return true; 49 } 50 int main () 51 { 52 scanf("%d%d%d",&n,&s,&m); 53 Create(tot=1,1,n),b=-1; 54 for(int i=1;i<=s;i++) 55 { 56 scanf("%d%d",&pos,&rd); 57 mem[num[pos]]=rd; 58 } 59 for(int i=1;i<=m;i++) 60 { 61 scanf("%d%d%d",&t1,&t2,&t3); 62 int last=t1; tot++; 63 for(int j=1;j<=t3;j++) 64 { 65 scanf("%d",&rd); link(num[rd],tot,0); 66 if(last<rd) Change(1,1,n,last,rd-1,tot); 67 last=rd+1; 68 } 69 if(last<=t2) Change(1,1,n,last,t2,tot); 70 } 71 for(int i=1;i<=tot;i++) 72 dp[i]=mem[i]?mem[i]:maxx; 73 for(int i=1;i<=tot;i++) 74 { 75 if(!vis[i]&&!DFS(i)) GG(); 76 if(!deg[i]) que[++b]=i; 77 } 78 while(f<=b) 79 { 80 if(dp[tn=que[f++]]<1) GG(); 81 for(int i=p[tn];i;i=noww[i]) 82 { 83 if(dp[tn]-val[i]<mem[goal[i]]) GG(); 84 dp[goal[i]]=min(dp[goal[i]],dp[tn]-val[i]); 85 if(!(--deg[goal[i]])) que[++b]=goal[i]; 86 } 87 } 88 printf("TAK "); 89 for(int i=1;i<=n;i++) printf("%d ",dp[num[i]]); 90 return 0; 91 }