UOJ 486 在路上了

考虑除开\(1-k\)以外的任意点\(d\)在长度为\(k-1\)的链上有:

对于任意\(i,i+1 (i\in [1,k-1])\)\(col[d][i]+col[d][i+1]<2\),否则我们可以直接输出一个红色的\(k\)条边的链。

30pts

\(2k=n\)的时候,我们考虑两个点(p,q),如果两者之间是\(0\)直接连上去,如果是1则我们考虑在\(1-k\)中选两个点(a,a+1),查询(p或q)->(a或a+1) 的颜色。发现我们一定能找到一条p -> (a或a+1) -> q的路径,否则可以输出红边的答案。

70pts

30pts的问题主要是如果每次第一次查询颜色都是蓝色则会导致长度不够,考虑三个点p,q,r的时候,我们查寻\(6\)次,至少有\(3\)\(0\)边,也就是说至少可以让两个点中间插两条边。

这样我们可以变成只剩两条链。用一个端点链接变成一条链

如果是\(1/2k\)\(>k\)的点,现在会剩下3个点,一个是端点,发现正好可以在两边多拓展一个,这样刚好可以凑出来一个\(k\)条边的。

100pts

\(6\)次查询优化成\(4\)次即可。先查p->a,q->a,如果同色,则最多再花两次询问找一个。如果不同色,则查询r->a+1,之后无论如何都只用再查询一次。这样最多查询\(4\)

代码

#include <bits/stdc++.h>
#include "graph.h"
using namespace std;
typedef pair<int,int> pii;
map<pair<int,int>, int> table;
inline int qry(int x,int y){
	if(x>y)swap(x,y);
	if(table.find(pii(x,y))==table.end())
		return table[pii(x,y)]=query(x,y);
	else return table[pii(x,y)];
}
int KK;
struct link{
	int s,t;
	vector<int> node;
	link(int s=0,int t=0):s(s),t(t){node.push_back(s);}
	void rev(){
		reverse(node.begin(),node.end());
		swap(s,t);
	}
	inline void add(link y){
		t=y.t;
		for(size_t i=0;i<y.node.size();i++)node.push_back(y.node[i]);
	}
};
vector<link> Lk;
int curpos;
vector<int> Ret;
vector<int> gen(int p,int d){
	vector<int> r;
	for(int i=0;i<=KK;i++){
		if(i>0)r.push_back(i);
		if(i==p)r.push_back(d);
	}
	return r;
}
void push_back(link t){
	Lk.push_back(t);
}
bool End;
inline void merge(link a,link b,link c){
	link nw;
	int d1=qry(a.s,curpos-1);
	int d2=qry(b.s,curpos-1);
	if(d1==d2&&d2==0){
		nw=a;nw.rev();nw.node.push_back(curpos-1);
		nw.add(b);
		push_back(c);push_back(nw);
		return ;
	}
	else if(d1==d2&&d2==1){
		if(qry(a.s,curpos)==1){
			Ret=gen(curpos-1,a.s);
			End=1;return ;
		}if(qry(b.s,curpos)==1){
			Ret=gen(curpos-1,b.s);
			End=1;return ;
		}
		nw=a;nw.rev();nw.node.push_back(curpos);
		nw.add(b);
		push_back(c);push_back(nw);
	}
	else{
		int d3=qry(c.s,curpos);
		if(d1==1)
			swap(a,b);//d1=0,d2=1
		if(!d3){
			if(qry(b.s,curpos)==1){
				Ret=gen(curpos-1,b.s);
				End=1;return ;
			}
			nw=b;nw.rev();nw.node.push_back(curpos);
			nw.add(c);
			push_back(a),push_back(nw);
		}else{
			if(qry(c.s,curpos-1)==1){
				Ret=gen(curpos-1,c.s);End=1;
				return;
			}
			nw=a;nw.rev();nw.node.push_back(curpos-1);
			nw.add(c);
			push_back(b),push_back(nw);
		}
	}
}
bool sp=0;
vector<int> find_longer_path(int n, int k) {
	KK=k;
	int n2=(k-1)/2+2;
	if(k+n2>n)n2--,sp=1;
	for(int j=k+1;j<=k+n2;j++){
		Lk.push_back(link(j,j));
	}
	curpos=3;
	while((int)Lk.size()>2){
		link a=Lk.back();Lk.pop_back();
		link b=Lk.back();Lk.pop_back();
		link c=Lk.back();Lk.pop_back();
		merge(a,b,c);
		if(End)return Ret;
		curpos+=2;
	}
	link a=Lk[0], b=Lk[1];
	if(qry(a.s,1))return gen(0,a.s);
	if(qry(b.s,1))return gen(0,b.s);
	a.rev();a.node.push_back(1);a.add(b);
	if((int)a.node.size()>=k+1){
		while((int)a.node.size()>k+1)a.node.pop_back();
		return a.node;
	}else{
		if(qry(a.t,k)){
			return gen(k,a.t);
		}
		a.node.push_back(k);a.t=k;
		if(a.node.size()<k+1){
			a.rev();
			int d2=qry(k-1,a.t);
			int d3=qry(k-2,a.t);
			if(d2&&d3)return gen(k-2,a.t);
			else if(!d2){
				a.node.push_back(k-1);
			}else if(!d3){
				a.node.push_back(k-2);
			}
		}
		return a.node;
	}
}
posted @ 2019-08-12 16:06  jerome_wei  阅读(249)  评论(0编辑  收藏  举报