• bzoj4383: [POI2015]Pustynia


    Description

    给定一个长度为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个数大(严格大于,即没有等号)。
    请任意构造出一组满足条件的方案,或者判断无解。

    Input

    第一行包含三个正整数n,s,m(1<=s<=n<=100000,1<=m<=200000)。
    接下来s行,每行包含两个正整数p[i],d[i](1<=p[i]<=n,1<=d[i]<=10^9),表示已知a[p[i]]=d[i],保证p[i]递增。
    接下来m行,每行一开始为三个正整数l[i],r[i],k[i](1<=l[i]<r[i]<=n,1<=k[i]<=r[i]-l[i]),接下来k[i]个正整数x[1],x[2],...,x[k[i]](l[i]<=x[1]<x[2]<...<x[k[i]]<=r[i]),表示这k[i]个数中的任意一个都比任意一个剩下的r[i]-l[i]+1-k[i]个数大。Σk <= 300,000

    Output

    若无解,则输出NIE。
    否则第一行输出TAK,第二行输出n个正整数,依次输出序列a中每个数。

    对大小关系用有向边表示,通过拓扑排序可以构造出一组可行解,由于直接连边边数过大,需要用线段树优化建图
     
    #include<cstdio>
    char buf[10000007],*ptr=buf-1;
    int _(){
        int x=0,c=*++ptr;
        while(c<48)c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x;
    }
    bool ed[1000007];
    int n,s,m,mx=1,m2;
    int v[1000007],in[1000007],vp,q[1000007],ql=0,qr=0;
    int es[12000007][2],e0[1000007],ep=2;
    void ae(int a,int b){
        es[ep][0]=b;es[ep][1]=e0[a];e0[a]=ep++;
        ++in[b];
    }
    void ins(int l,int r,int a){
        if(l<=r)
        for(l+=mx-1,r+=mx+1;l^r^1;l>>=1,r>>=1){
            if(~l&1)ae(a,l^1);
            if(r&1)ae(a,r^1);
        }
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin);
        n=_();s=_();m=_();
        while(mx<n+3)mx<<=1;
        while(s--){
            int x=_();
            v[mx+x]=_();
            ed[mx+x]=1;
        }
        for(int i=1;i<mx;++i)ae(i,i<<1),ae(i,i<<1^1);
        m2=vp=mx<<1;
        while(m--){
            int l=_(),r=_(),k=_();
            for(int i=0,x;i<k;++i){
                x=_();
                ae(mx+x,vp);
                ins(l,x-1,vp);
                l=x+1;
            }
            ins(l,r,vp++);
        }
        for(int i=1;i<vp;++i)if(!v[i])v[i]=1000000000;
        q[++qr]=1;
        while(ql!=qr){
            int w=q[++ql];
            if(w>=m2)--v[w];
            if(v[w]<1)return puts("NIE"),0;
            for(int i=e0[w];i;i=es[i][1]){
                int u=es[i][0];
                if(v[u]>v[w]){
                    if(ed[u])return puts("NIE"),0;
                    else v[u]=v[w];
                }
                if(!--in[u])q[++qr]=u;
            }
        }
        if(qr+1!=vp)return puts("NIE"),0;
        puts("TAK");
        for(int i=1;i<=n;++i)printf("%d ",v[i+mx]);
        return 0;
    }
  • 相关阅读:
    Java Stax操作XML简介
    使用JAXB来实现Java合xml之间的转换
    WebService学习笔记系列(四)
    JavaWeb学习笔记总结 目录篇
    成为谷歌的java程序员首先要做到这五点!
    Java实现快速排序
    二叉树遍历(Java实现)
    Java单链表反转
    学好java,做好工程师必读的15本书
    最全前端资源汇集
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6417791.html
Copyright © 2020-2023  润新知