1. 程式人生 > >BZOJ4383 Pustynia(線段樹+拓撲排序)

BZOJ4383 Pustynia(線段樹+拓撲排序)

inf fin () edge long 葉子 getch cout tree

  線段樹優化建圖暴力拓撲排序即可。對於已確定的數,拓撲排序時dp,每個節點都盡量取最大值,如果仍與已確定值矛盾則無解。葉子連出的邊表示大於號,其余邊表示大於等於。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
#define inf 1000000000
char
getc(){char c=getchar();while ((c<A||c>Z)&&(c<a||c>z)&&(c<0||c>9)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<0||c>9) {if (c==-) f=-1;c=getchar();} while
(c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,s,m,a[N<<4],b[N],c[N],p[N<<4],id[N],pos[N<<4],degree[N<<4],q[N<<4],t,root,cnt; bool flag[N]; struct data{int to,nxt; }edge[N<<7]; struct data2{int l,r; }tree[N<<2
]; void addedge(int x,int y){t++;degree[y]++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void build(int &k,int l,int r) { k=++cnt;a[k]=inf; if (l==r) {id[l]=k,pos[k]=l;if (flag[l]) a[k]=c[l];return;} int mid=l+r>>1; build(tree[k].l,l,mid); build(tree[k].r,mid+1,r); addedge(k,tree[k].l), addedge(k,tree[k].r); } void add(int p,int k,int l,int r,int x,int y) { if (l==x&&r==y) {addedge(p,k);return;} int mid=l+r>>1; if (y<=mid) add(p,tree[k].l,l,mid,x,y); else if (x>mid) add(p,tree[k].r,mid+1,r,x,y); else add(p,tree[k].l,l,mid,x,mid),add(p,tree[k].r,mid+1,r,mid+1,y); } bool topsort() { int head=0,tail=0;for (int i=1;i<=cnt;i++) if (!degree[i]) q[++tail]=i; while (head<tail) { int x=q[++head],y=a[x]-(pos[x]>0); for (int i=p[x];i;i=edge[i].nxt) { degree[edge[i].to]--; if (flag[pos[edge[i].to]]) { if (a[edge[i].to]>y) return cout<<"NIE"<<endl,0; } else a[edge[i].to]=min(a[edge[i].to],y); if (!degree[edge[i].to]) q[++tail]=edge[i].to; } } if (tail<cnt) return cout<<"NIE"<<endl,0; else return cout<<"TAK"<<endl,1; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4383.in","r",stdin); freopen("bzoj4383.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),s=read(),m=read(); for (int i=1;i<=s;i++) { int x=read(),y=read(); c[x]=y;flag[x]=1; } build(root,1,n); for (int i=1;i<=m;i++) { int l=read(),r=read(),k=read(); for (int j=1;j<=k;j++) b[j]=read(); b[0]=l-1,b[k+1]=r+1; cnt++;a[cnt]=inf; for (int j=1;j<=k+1;j++) if (b[j-1]+1<=b[j]-1) add(cnt,root,1,n,b[j-1]+1,b[j]-1); for (int j=1;j<=k;j++) addedge(id[b[j]],cnt); } if (topsort()) for (int i=1;i<=n;i++) printf("%d ",a[id[i]]); return 0; }

BZOJ4383 Pustynia(線段樹+拓撲排序)