BZOJ4383 Pustynia(线段树+拓扑排序)
线段树优化建图暴力拓扑排序即可。对于已确定的数,拓扑排序时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; }