题目描述
给定一个长度为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个数大(严格大于,即没有等号)。请任意构造出一组满足条件的方案,或者判断无解。
输入输出格式
输入格式:
第一行包含三个正整数n,s,m(1<=s<=n<=100000,1<=m<=200000)。接下来s行,每行包含两个正整数p[i],di,表示已知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
输出格式:
若无解,则输出NIE。否则第一行输出TAK,第二行输出n个正整数,依次输出序列a中每个数。
输入输出样例
输入样例#1: 复制
5 2 2
2 7
5 3
1 4 2 2 3
4 5 1 4
输出样例#1: 复制
TAK
6 7 1000000000 6 3
说明
给定一个长度为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个数大(严格大于,即没有等号)。
请任意构造出一组满足条件的方案,或者判断无解。
线段树建图优化模板,首先运用差分约束的思想,如果存在环则无解。因此可行解一定是个DAG,然后就是连边乱搞,发现强行乱搞是n^2,于是我们就要加优化。又发现一段连续的区间如果都连一条边十分浪费,又因为是连续的区间,想到用线段树去优化。
至于线段树中儿子连父亲还是父亲连儿子,视写法而定(我感觉挺玄乎的)。
#include<bits/stdc++.h>
using namespace std;
const int Maxn=100000*log2(100000);
int n,s,m,v[Maxn],f[Maxn],d[Maxn],x[Maxn];
int tot,p[Maxn];
bool vst[Maxn];
struct Edge{
int cnt,h[Maxn],w[Maxn*2],to[Maxn*2],next[Maxn*2];
inline void add(int x,int y,int z){
next[++cnt]=h[x];to[cnt]=y;w[cnt]=z;h[x]=cnt;++d[y];
}
}e;
#define to e.to[p]
struct SegMent{
struct tree{
int ls,rs,l,r;
}t[Maxn*2];int root;
inline void link(int x,int l,int r,int y){
// cout<<l<<" "<<r<<"\n";
if(t[x].l>r||t[x].r<l)return ;
if(l<=t[x].l&&t[x].r<=r){
// cout<<x<<" "<<y<<"\n";
return e.add(y,x,0),void();
}
link(t[x].ls,l,r,y),link(t[x].rs,l,r,y);
}
inline void build(int &x,int l,int r){
t[x=++tot]=(tree){0,0,l,r};
int mid=l+r>>1;
if(l==r)return p[mid]=x,void();
build(t[x].ls,l,mid),build(t[x].rs,mid+1,r);
e.add(x,t[x].ls,0),e.add(x,t[x].rs,0);
}
}seg;
inline bool topsort(){
queue<int>Q;
for(int i=1;i<=tot;++i)f[i]=v[i]?v[i]:1e9;
for(int i=1;i<=tot;++i)if(!d[i])Q.push(i);
while(!Q.empty()){
int x=Q.front();Q.pop();
if(f[x]<v[x])return 0;
vst[x]=1;
for(int p=e.h[x];p;p=e.next[p]){
// cout<<to<<"\n";
f[to]=min(f[to],f[x]+e.w[p]);
if(--d[to]==0)Q.push(to);
}
}
for(int i=1;i<=tot;++i)if(!vst[i])return 0;
return 1;
}
int main(){
scanf("%d%d%d",&n,&s,&m);
seg.build(seg.root,1,n);
// memset(v,63,sizeof(v));
for(int i=1;i<=s;++i){
int x,k;scanf("%d%d",&x,&k);
v[p[x]]=k;
}
for(int i=1;i<=m;++i){
int l,r,k;scanf("%d%d%d",&l,&r,&k);
++tot;for(int j=1;j<=k;++j){
scanf("%d",&x[j]);
e.add(p[x[j]],tot,-1);
}
x[0]=l-1;x[k+1]=r+1;
for(int j=0;j<=k;++j){
seg.link(seg.root,x[j]+1,x[j+1]-1,tot);
}
}
if(!topsort())puts("NIE");
else {
puts("TAK");
for(int i=1;i<=n;++i)cout<<f[p[i]]<<" ";
}
return 0;
}