【2021集训队出题】序列

【2021集训队出题】序列

by AmanoKumiko

Description

有一个长度为\(n\)的序列\(a\),其中\(a_i∈[1,10^9]\)

给出\(m\)个限制,每次给出\(i,j,k,x\),你需要满足\(a_i,a_j,a_k\)中的中位数为\(x\)

给出一组合法解

Input

第一行两个数\(n,m\)

接下来\(m\)行,读入限制

Output

若有解,第一行输出\(YES\),然后输出\(n\)个整数表示\(a\)

反之输出\(NO\)

Sample Input

6 4
1 3 4 2
1 2 5 6
3 6 6 7
2 4 5 3

Sample Output

YES
6 8 2 2 3 7

Data Constraint

\(1\le n,m\le 10^5,1\le i,j,k\le n,1\le x\le 10^9\)

Solution

尝试用\(2-SAT\)解决问题

我们设一个变量\(X(i,j)\),若为\(1\),表示\(a_i\ge j\),若为\(0\),表示\(a_i<j\)

那么每次给出限制,我们只需要形如\(X(i,x)=0\)\(X(j,x)=1\)连,\(X(i,x)=0\)\(X(k,x)=1\)

但是这样的话点特别多,考虑优化

显然,\(a\)中的值只可能是题目给出的\(x\),若不是,则可以调整

那么我们对每个\(i\)建出它的可能的数的集合,然后拿个\(set\)处理一下就好了

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define N 100010
#define S 1000010

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
cc_hash_table<int,int>num[N][2];

set<int>s[N];
set<int>::iterator it;
int n,m,nt,ans[N];
int low[S],dfn[S],cnt,tot,last[S],scc[S],in[S],st[S],top,col;
struct edge{int en,next;}e[S*10];
struct node{int i,j,k,x,kind;}ask[N];

void add(int x,int y){e[++tot]=(edge){y,last[x]};last[x]=tot;}

void Tarjan(int x){
	dfn[x]=low[x]=++cnt;st[++top]=x;in[x]=1;
	for(int i=last[x];i;i=e[i].next){
		int y=e[i].en;
		if(!dfn[y])Tarjan(y),low[x]=min(low[x],low[y]);
		else if(in[y])low[x]=min(low[x],dfn[y]);
	}
	if(low[x]==dfn[x]){
		col++;
		while(st[top]!=x)in[st[top]]=0,scc[st[top--]]=col;
		in[st[top]]=0;scc[st[top--]]=col;
	}
}

int main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%d%d",&n,&m);
	F(i,1,n)s[i].insert(1),s[i].insert(1000000000);
	F(i,1,m){
		scanf("%d%d%d%d",&ask[i].i,&ask[i].j,&ask[i].k,&ask[i].x);
		if(ask[i].i==ask[i].j&&ask[i].j==ask[i].k)ask[i].kind=1;
		else if(ask[i].i==ask[i].j||ask[i].j==ask[i].k||ask[i].i==ask[i].k)ask[i].kind=2;
		else ask[i].kind=3;
		s[ask[i].i].insert(ask[i].x);
		s[ask[i].j].insert(ask[i].x);
		s[ask[i].k].insert(ask[i].x);
	}
	F(i,1,n){
		int lnt=nt;
		for(it=s[i].begin();it!=s[i].end();it++)num[i][0][*it]=++nt,num[i][1][*it]=++nt;
		for(int j=lnt+1;j<nt-2;j+=2)add(j,j+2);
		for(int j=lnt+4;j<=nt;j+=2)add(j,j-2);
	}
	F(i,1,m){
		int si,ei,sj,ej,sk,ek;
		it=s[ask[i].i].lower_bound(ask[i].x);si=num[ask[i].i][0][*it];ei=num[ask[i].i][1][*it];
		it=s[ask[i].j].lower_bound(ask[i].x);sj=num[ask[i].j][0][*it];ej=num[ask[i].j][1][*it];
		it=s[ask[i].k].lower_bound(ask[i].x);sk=num[ask[i].k][0][*it];ek=num[ask[i].k][1][*it];
		if(ask[i].kind==1){
			if(ans[ask[i].i]&&ans[ask[i].i]!=ask[i].x){printf("NO");return 0;}
			ans[ask[i].i]=ask[i].x;
		}else add(si,ej),add(si,ek),add(sj,ei),add(sj,ek),add(sk,ei),add(sk,ej);
		it=s[ask[i].i].upper_bound(ask[i].x);si=num[ask[i].i][1][*it];ei=num[ask[i].i][0][*it];
		it=s[ask[i].j].upper_bound(ask[i].x);sj=num[ask[i].j][1][*it];ej=num[ask[i].j][0][*it];
		it=s[ask[i].k].upper_bound(ask[i].x);sk=num[ask[i].k][1][*it];ek=num[ask[i].k][0][*it];
		if(ask[i].kind==1){
			if(ans[ask[i].i]&&ans[ask[i].i]!=ask[i].x){printf("NO");return 0;}
			ans[ask[i].i]=ask[i].x;
		}else add(si,ej),add(si,ek),add(sj,ei),add(sj,ek),add(sk,ei),add(sk,ej);
	}
	F(i,1,nt)if(!dfn[i])Tarjan(i);
	F(i,1,n){
		int lst=0,wh=0;
		for(it=s[i].begin();it!=s[i].end();it++){
			if(scc[num[i][0][*it]]==scc[num[i][1][*it]]){printf("NO");return 0;}
			if(scc[num[i][0][*it]]<scc[num[i][1][*it]]&&!ans[i])ans[i]=lst;
			lst=*it;
		}
		if(!ans[i])ans[i]=1;
	}
	printf("YES\n");
	F(i,1,n)printf("%d ",ans[i]);
	return 0;
}
posted @ 2022-01-19 20:38  冰雾  阅读(76)  评论(0编辑  收藏  举报