Nanami and the Constructive Problem

D06發表於2024-07-06
  • 線段樹最佳化建圖
  • 一般用動態開點線段樹實現
  • 建立對稱的入樹和出樹
點選檢視程式碼
#include <bits/stdc++.h>
using namespace std;
vector<int>a[600005];
int c[100005],cnt,tot,sum,id[600005],dfn[600005],low[600005],val[100005],n,m;
stack<int>s;
bool v[600005],h[600005];
int root1,root2;
int read1()
{
	char cc=getchar();
	while(!(cc>=48&&cc<=57))
	{
		if(cc=='-')
		{
			break;
		}
		cc=getchar();
	}
	bool f=false;
	int s=0;
	if(cc=='-')
	{
		f=true;
	}
	else
	{
		s=cc-48;
	}
	while(1)
	{
		cc=getchar();
		if(cc>=48&&cc<=57)
		{
			s=s*10+cc-48;
		}
		else
		{
			break;
		}
	}
	if(f==true)
	{
		s=-s;
	}
	return s;
}
struct t1
{
	int l,r;
}t[600005];
struct w1
{
	int va,id;
}w[100005];
int tmp[100005];
bool cmp(w1 a,w1 b)
{
	return a.va<b.va;
}
int build1(int l,int r)
{
	int p;
	if(l==r)
	{
		p=l;
		return p;
	}
	else
	{
		p=++tot;
		a[p].clear();
	}
	int mid=(l+r)>>1;
	t[p].l=build1(l,mid);
	t[p].r=build1(mid+1,r);
	a[p].push_back(t[p].l);
	a[p].push_back(t[p].r);
	return p;
}
int build2(int l,int r)
{
	int p;
	if(l==r)
	{
		p=l;
		return p;
	}
	else
	{
		p=++tot;
		a[p].clear();
	}
	int mid=(l+r)>>1;
	t[p].l=build2(l,mid);
	t[p].r=build2(mid+1,r);
	a[t[p].l].push_back(p);
	a[t[p].r].push_back(p);
	return p;
}
void change1(int p,int pl,int pr,int l,int r,int c,int opt)
{
	if(l<=pl&&r>=pr)
	{
		if(opt==1) 
		{
			a[c].push_back(p);
		}
		else
		{
			a[c].pop_back();
		}
	}
	else
	{
		int mid=(pl+pr)>>1;
		if(l<=mid)
		{
			change1(t[p].l,pl,mid,l,r,c,opt);
		}
		if(r>mid)
		{
			change1(t[p].r,mid+1,pr,l,r,c,opt);
		}
	}
}
void change2(int p,int pl,int pr,int l,int r,int c,int opt)
{
	if(l<=pl&&r>=pr)
	{
		if(opt==1) 
		{
			a[p].push_back(c);
		}
		else
		{
			a[p].pop_back();
		}
	}
	else
	{
		int mid=(pl+pr)>>1;
		if(l<=mid)
		{
			change2(t[p].l,pl,mid,l,r,c,opt);
		}
		if(r>mid)
		{
			change2(t[p].r,mid+1,pr,l,r,c,opt);
		}
	}
}
void tarjan(int n1)
{
	v[n1]=true;
	s.push(n1);
	h[n1]=true;
	dfn[n1]=++tot;
	low[n1]=dfn[n1];
	for(int i=0;i<a[n1].size();i++)
	{
		if(v[a[n1][i]]==false)
		{
			tarjan(a[n1][i]);
			low[n1]=min(low[n1],low[a[n1][i]]);
		}
		else if(h[a[n1][i]]==true)
		{
			low[n1]=min(low[n1],dfn[a[n1][i]]);
		}
	}
	if(dfn[n1]==low[n1])
	{
		cnt++;
		while(!s.empty())
		{
			if(s.top()==n1)
			{
				break;
			}
			h[s.top()]=false;
			id[s.top()]=cnt;
			s.pop();
		}
		h[n1]=false;
		id[n1]=cnt;
		s.pop();
	}
}
bool solve()
{
	for(int i=1;i<=6*n;i++)
	{
		dfn[i]=0;
		v[i]=false;
	}
	tot=cnt=0;
	for(int i=1;i<=6*n;i++)
	{
		if(dfn[i]==0)
		{
			tarjan(i);
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(id[val[i]]==id[val[i]+n])
		{
			return false;
		}
		c[i]=id[val[i]]>id[val[i]+n];
	}
	return true;
}
void change(int maxn,int opt)
{
	for(int i=1;i<=n;i++)
	{
		int j=upper_bound(tmp+i+1,tmp+n+1,tmp[i]+maxn)-tmp;
		if(j!=n+1)
		{
			change1(root1,1,2*n,j,n,i+n,opt);
			change2(root2,1,2*n,j+n,n+n,i,opt);
		}
	}
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		n=read1();
		m=read1();
		for(int i=1;i<=n;i++)
		{
			w[i].va=read1();
			w[i].id=i;
		}
		sort(w+1,w+n+1,cmp);
		for(int i=1;i<=n;i++)
		{
			val[w[i].id]=i;
			tmp[i]=w[i].va;
		}
		for(int i=1;i<=2*n;i++)
		{
			a[i].clear();
		}
		tot=2*n;
		root1=build1(1,2*n);
		root2=build2(1,2*n);
		for(int i=1;i<=m;i++)
		{
			int x,y,l,r;
			x=read1();
			y=read1();
			l=read1();
			r=read1();
			if(l==0&&r==2)
			{
				
			}
			else if(l==r)
			{
				if(l==0)
				{
					a[val[x]+n].push_back(val[x]);
					a[val[y]+n].push_back(val[y]);
				}
				else if(l==2)
				{
					a[val[x]].push_back(val[x]+n);
					a[val[y]].push_back(val[y]+n);
				}
				else
				{
					a[val[x]].push_back(val[y]+n);
					a[val[y]+n].push_back(val[x]);
					a[val[y]].push_back(val[x]+n);
					a[val[x]+n].push_back(val[y]);
				}
			}
			else
			{
				if(l==0)
				{
					a[val[x]+n].push_back(val[y]);
					a[val[y]+n].push_back(val[x]);
				}
				else
				{
					a[val[x]].push_back(val[y]+n);
					a[val[y]].push_back(val[x]+n);
				}
			}
		}
		int l=0,r=2e8;
		while(l<r)
		{
			int mid=(l+r)>>1;
			change(mid,1);
			bool tmp=solve();
			if(tmp==true)
			{
				r=mid;
			}
			else
			{
				l=mid+1;
			}
			change(mid,-1);
		}
		change(l,1);
		bool tmp=solve();
		if(tmp==false)
		{
			puts("-1");
			continue;
		}
		printf("%d\n",l);
		for(int i=1;i<=n;i++)
		{
			if(c[i]==1)
			{
				printf("1");
			}
			else
			{
				printf("0");
			}
		}
		printf("\n");
	}
	return 0;
}

相關文章