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