[bzoj 4383--POI2015]Pustynia

給定一個長度爲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個數大(嚴格大於,即沒有等號)。
請任意構造出一組滿足條件的方案,或者判斷無解。

這道題首先運用差分約束的思想,把小的往大的連邊,然後拓撲排序一下之後,再判斷一下細節就可以了。對於邊數過多的問題,用線段樹優化建邊就可以了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<queue>
#define inf 1000000000
using namespace std;
queue<int>q;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
struct node
{
    int x,y,c,next;
}a[2000010];int id,len,ru[400010],last[400010];
inline void ins(int x,int y,int c)
{
    len++;ru[y]++;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;
}
struct trnode
{
    int l,r,lc,rc;
}tr[200010];int trlen;
int ex[100010];
inline void bt(int l,int r)
{
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;
    if(l==r)ex[l]=now;
    else
    {
        int mid=(l+r)>>1;
        tr[now].lc=trlen+1;ins(tr[now].lc,now,0),bt(l,mid);
        tr[now].rc=trlen+1;ins(tr[now].rc,now,0),bt(mid+1,r);
    }
}
inline void Link(int now,int l,int r)
{
    if(l>r)return ;
    if(tr[now].l==l && tr[now].r==r){ins(now,id,1);return ;}
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)>>1;
    if(r<=mid)Link(lc,l,r);
    else if(mid+1<=l)Link(rc,l,r);
    else Link(lc,l,mid),Link(rc,mid+1,r);
}
int f[400010],ul[400010];
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    int n=read(),cnt=read(),m=read();bt(1,n),id=trlen;
    for(int i=1;i<=cnt;i++){int p=read(),d=read();f[ex[p]]=d,ul[ex[p]]=d;}
    for(int i=1;i<=m;i++)
    {
        id++;int l=read(),r=read(),k=read(),lt=l;
        for(int j=1;j<=k;j++){int p=read();ins(id,ex[p],0),Link(1,lt,p-1);lt=p+1;}
        Link(1,lt,r);
    }
    for(int i=1;i<=id;i++)if(!ru[i]){q.push(i);if(!f[i])f[i]=1;}
    while(q.empty()!=true)
    {
        int x=q.front();q.pop();
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            f[y]=max(f[y],f[x]+a[k].c);
            ru[y]--;if(ru[y]==0)q.push(y);
        }
    }
    bool bk=true;
    for(int i=1;i<=id;i++)if(f[i]<1 || f[i]>inf || ru[i] || (f[i]>ul[i] && ul[i])){bk=false;break;}
    if(bk==false)printf("NIE\n");
    else
    {
        printf("TAK\n");
        for(int i=1;i<=n;i++)printf("%d ",f[ex[i]]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章