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;
}

 

posted @ 2019-01-18 10:56  Gloid  阅读(255)  评论(0编辑  收藏  举报