結果

問題 No.274 The Wall
ユーザー snteasntea
提出日時 2017-02-20 03:58:42
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 577 ms / 2,000 ms
コード長 9,608 bytes
コンパイル時間 2,222 ms
コンパイル使用メモリ 193,992 KB
実行使用メモリ 198,168 KB
最終ジャッジ日時 2024-06-22 02:12:53
合計ジャッジ時間 4,374 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,816 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 216 ms
78,756 KB
testcase_04 AC 2 ms
6,940 KB
testcase_05 AC 2 ms
6,940 KB
testcase_06 AC 2 ms
6,940 KB
testcase_07 AC 2 ms
6,940 KB
testcase_08 AC 2 ms
6,944 KB
testcase_09 AC 2 ms
6,940 KB
testcase_10 AC 2 ms
6,944 KB
testcase_11 AC 577 ms
198,168 KB
testcase_12 AC 11 ms
6,944 KB
testcase_13 AC 2 ms
6,944 KB
testcase_14 AC 5 ms
6,940 KB
testcase_15 AC 9 ms
6,940 KB
testcase_16 AC 126 ms
52,744 KB
testcase_17 AC 119 ms
49,988 KB
testcase_18 AC 130 ms
54,220 KB
testcase_19 AC 15 ms
6,940 KB
testcase_20 AC 16 ms
6,940 KB
testcase_21 AC 17 ms
6,940 KB
testcase_22 AC 19 ms
6,940 KB
testcase_23 AC 18 ms
6,944 KB
testcase_24 AC 19 ms
6,944 KB
testcase_25 AC 18 ms
6,940 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#ifdef LOCAL111
	#define _GLIBCXX_DEBUG
#else
	#define NDEBUG
#endif
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
const int INF = 1e9;
using namespace std;
template<typename T, typename U> ostream& operator<< (ostream& os, const pair<T,U>& p) { cout << '(' << p.first << ' ' << p.second << ')'; return os; }

#define endl '\n'
#define ALL(a)  (a).begin(),(a).end()
#define SZ(a) int((a).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define REP(i,n)  FOR(i,0,n)
#define RREP(i,n) for (int i=(n)-1;i>=0;i--)
#ifdef LOCAL111
	#define DEBUG(x) cout<<#x<<": "<<(x)<<endl
	template<typename T> void dpite(T a, T b){ for(T ite = a; ite != b; ite++) cout << (ite == a ? "" : " ") << *ite; cout << endl;}
#else
	#define DEBUG(x) true
	template<typename T> void dpite(T a, T b){ return; }
#endif
#define F first
#define S second
#define SNP string::npos
#define WRC(hoge) cout << "Case #" << (hoge)+1 << ": "
template<typename T> void pite(T a, T b){ for(T ite = a; ite != b; ite++) cout << (ite == a ? "" : " ") << *ite; cout << endl;}
template<typename T> bool chmax(T& a, T b){if(a < b){a = b; return true;} return false;}
template<typename T> bool chmin(T& a, T b){if(a > b){a = b; return true;} return false;}



//library
typedef long long cost_t;

// class Edge {
// public:
// 	int to = -1, from = -1, rev = -1;
// 	cost_t cost = -1;
	
// 	Edge(){
// 	}

// 	Edge(int x,cost_t y){
// 		to = x;
// 		cost = y;
// 	}

// 	Edge(int x, int y, cost_t z){
// 		from = x;
// 		to = y;
// 		cost = z;
// 	}

// 	Edge(int x, int y, int r, cost_t z){
// 		from = x;
// 		to = y;
// 		cost = z;
// 		rev = r;
// 	}

// 	bool operator< (const Edge& x) const {
// 		if(cost != x.cost) return cost < x.cost;
// 		return to < x.to;
// 	}

// 	bool operator> (const Edge& x) const {
// 		if(cost != x.cost) return cost > x.cost;
// 		return to > x.to;
// 	}
// };

class Edge {
public:
	int to = -1;//, from = -1, rev = -1;
	// cost_t cost = -1;
	
	Edge(){
	}

	Edge(int x,cost_t y){
		to = x;
		// cost = y;
	}

	Edge(int x, int y, cost_t z){
		// from = x;
		to = y;
		// cost = z;
	}

	Edge(int x, int y, int r, cost_t z){
		// from = x;
		to = y;
		// cost = z;
		// rev = r;
	}

	bool operator< (const Edge& x) const {
		// if(cost != x.cost) return cost < x.cost;
		return to < x.to;
	}

	bool operator> (const Edge& x) const {
		// if(cost != x.cost) return cost > x.cost;
		return to > x.to;
	}
};

class Graph {
private:
	typedef vector<Edge> Edges;
	//const long long int INF = (long long)1e18;
	vector<Edges> v; 
	int n;
public:
	Graph(int x){
		n = x;
		v = vector<Edges>(x);
	}

	Graph(){}

	Edges& operator[](int x){
		return v[x];
	}

	const Edges& operator[](int x) const {
		return v[x];
	}

	int size() const {
		return n;
	}

	void add_edge(int from, const Edge &e){
		v[from].push_back(e);
	}

	void add_edge(int from, int to, cost_t cost = -1, int rev = -1){
		add_edge(from,Edge(from,to,rev,cost));
	}

	void add_uedge(int from, int to, cost_t cost = -1){
		add_edge(from,to,cost);
		add_edge(to,from,cost);
	}
};


// vector<cost_t> dijkstra(int from, const Graph& v)
// {
// 	vector<cost_t> dist(v.size(),INF);
// 	priority_queue<Edge,vector<Edge>,greater<Edge>> que;
// 	que.push(Edge(from,0));
// 	while(!que.empty()){
// 		Edge e = que.top();
// 		que.pop();
// 		if(dist[e.to] == INF){
// 			dist[e.to] = e.cost;
// 			for(auto to : v[e.to]){
// 				if(dist[to.to] == INF)
// 					que.push(Edge(to.to, e.cost+to.cost));
// 			}
// 		}
// 	}
// 	return dist;
// }

// vector<cost_t> bellmanford(int from, const Graph& g)
// {
// 	vector<cost_t> res(g.size(),INF);
// 	res[from] = 0;
// 	bool conf = true;
// 	int cnt = 0;
// 	while(conf){
// 		conf = false;
// 		for(int i = 0; i < g.size(); i++){
// 			if(res[i] != INF)
// 			for(const auto& e : g[i]){
// 				if(res[e.to] > res[i]+e.cost){
// 					conf = true;
// 					res[e.to] = res[i]+e.cost;
// 				}
// 			}
// 		}
// 		if(cnt > g.size()+5) return vector<cost_t>();
// 		cnt++;
// 	}
// 	return res;
// }

// Graph prim(const Graph g)
// {
// 	using T = tuple<cost_t, int, int>;
// 	priority_queue<T, vector<T>, greater<T>> qu;
// 	int n = g.size();
// 	assert(n != 0);
// 	vector<bool> added(n,false);
// 	qu.emplace(0,0,0);
// 	Graph res(n);
// 	while(!qu.empty()){
// 		int from, to;
// 		cost_t cost;
// 		tie(cost, from, to) = qu.top();
// 		qu.pop();
// 		if(!added[to]){
// 			added[to] = true;
// 			res.add_edge(from, to, cost);
// 			res.add_edge(to, from, cost);
// 			for(const auto &e : g[to]){
// 				if(!added[e.to]){
// 					qu.emplace(e.cost, to, e.to);
// 				}
// 			}
// 		}
// 	}
// 	return res;
// }

vector<int> getTreeOrder(const Graph &g, int root)
{
	vector<int> res;
	function<void(int p, int pre)> func = [&](int p, int pre){
		for(auto &e : g[p]){
			if(e.to != pre){
				func(e.to,p);
			}
		}
		res.push_back(p);
	};
	func(root,-1);
	return res;
}

vector<int> getTreePar(const Graph &g, int root)
{
	vector<int> par(g.size(),root);
	function<void(int p, int pre)> func = [&](int p, int pre){
		par[p] = pre;
		for(auto &e : g[p]){
			if(e.to != pre){
				func(e.to,p);
			}
		}
	};
	func(root,root);
	return par;
}


vector<int> toposort(const Graph &g)
{
	int n = g.size();
	vector<int> res;
	res.reserve(n);
	vector<bool> used(n,false);
	function<void(int)> rec = [&](int p){
		if(used[p]) return;
		used[p] = true;
		for(auto&& e : g[p]) {
			rec(e.to);
		}
		res.push_back(p);
	};
	for(int i = 0; i < n; ++i) {
		if(!used[i]) rec(i);
	}
	reverse(res.begin(), res.end());
	return res;
}

// //0からの連結成分をたどる
// tuple<cost_t,int,int> getTreeDiameter(const Graph &g){
// 	using P = pair<cost_t,int>;
	
// 	function<P(int,int)> dfs = [&](int p, int par) -> P{
// 		P res = {0,p};
// 		for(auto&& e : g[p]) {
// 			if(e.to == par) continue;
// 			auto v = dfs(e.to,p);
// 			v.first += e.cost;
// 			res = max(res,v);
// 		}
// 		return res;
// 	};	
// 	auto ap1 = dfs(0,-1);
// 	auto ap2 = dfs(ap1.second,-1);
// 	return make_tuple(ap2.first,ap2.second,ap1.second);
// }

// // res.secondはなければ-1
// pair<int,int> getTreeCenter(const Graph& g){
// 	cost_t di;
// 	int x, y;
// 	tie(di, x, y) = getTreeDiameter(g);
// 	pair<int,int> res(-1,-1);
// 	cost_t mi;
// 	function<cost_t(int,int)> rec 
// 	 = [&](int p, int par) -> cost_t{
// 		if(p == y){
// 			return 0;
// 		}
// 		cost_t ress = -1;
// 		for(auto&& e : g[p]) if(e.to != par){
// 			cost_t v = rec(e.to,p);
// 			if(v != -1){
// 				v += e.cost;
// 				ress = v;
// 				v = max(v, di-(v));
// 				if(mi > v){
// 					mi = v;
// 					res = {p,-1};
// 				}else if(mi == v){
// 					res.second = p;
// 				}
// 			}
// 		}
// 		return ress;
// 	};
// 	rec(x,-1);
// 	return res;
// }
//liblary

tuple<vector<int>,int> SCC(const Graph &g)
{
	int n = g.size();
	vector<bool> used(n,false);
	vector<int> cmp(g.size());
	Graph rg(n);
	for(int i = 0; i < n; ++i) {
		for(auto&& e : g[i]) {
			rg.add_edge(e.to,i);//,e.cost);
		}
	}
	vector<int> vs;
	vs.reserve(g.size());
	
	function<void(int)> dfs = [&](int v){
		used[v] = true;
		for(auto&& e : g[v]) {
			if(!used[e.to]) dfs(e.to);
		}
		vs.push_back(v);
	};

	function<void(int,int)> rdfs = [&](int v, int k){
		used[v] = true;
		cmp[v] = k;
		for(auto&& e : rg[v]) {
			if(!used[e.to]) rdfs(e.to,k); 
		}
	};

	for(int v = 0; v < n; ++v) {
		if(!used[v]) dfs(v);
	}
	fill(used.begin(), used.end(), false);
	int k = 0;
	for(int i = n-1; i >= 0; --i) {
		if(!used[vs[i]]) rdfs(vs[i], k++);
	}
	return make_tuple(cmp,k);
}

Graph getSCCGraph(const Graph &g, vector<int> cmp, int k){
	Graph res(k);
	for(int p = 0; p < (int)g.size(); ++p) {
		for(auto&& e : g[p]) {
			res.add_edge(cmp[p],cmp[e.to]);//,e.cost,e.rev);
		}
	}
	return res;
}

//liblary

//Graph, scc に依存
class TwoSATsolver{
private:
	Graph g;
	int center;

public:
	TwoSATsolver(int n){
		center = n;
		g = Graph(2*n+1);
	}

	int f(int x){
		return center+x;
	}

	void add_clause(int x, int y){
		g.add_edge(f(-y),f(x));
		g.add_edge(f(-x),f(y));
	}

	//充足不可能なら空のvectorを返す
	vector<bool> solve(){
		DEBUG(g.cnt);
		// vizGraph(g);
		vector<int> cmp;
		int k;
		tie(cmp,k) = SCC(g);
		Graph retg = getSCCGraph(g,cmp,k);

		for(int i = 1; i <= center; ++i) {
			if(cmp[f(i)] == cmp[f(-i)]){
				return vector<bool>();
			}
		}

		vector<bool> res(center+1);
		for(int i = 1; i <= center; ++i) {
			int cmpi = cmp[f(i)];
			int cmpni = cmp[f(-i)];
			assert(cmpi != cmpni);
			if(cmpi < cmpni){
				res[i] = false;
			}else{
				res[i] = true;
			}
		}
		return res;
	}
};

typedef long long int LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;

void ios_init(){
	//cout.setf(ios::fixed);
	//cout.precision(12);
#ifdef LOCAL111
	return;
#endif
	ios::sync_with_stdio(false); cin.tie(0);	
}

int main()
{
	ios_init();
	int n,m;
	while(cin >> n >> m) {
		vector<P> lr(n);
		REP(i,n) cin >> lr[i].F >> lr[i].S;
		
		auto rev = [&](P p) -> P{
			return {m-1-p.S,m-1-p.F};
		};
		auto intersect = [&](P x, P y) -> bool{
			return not(x.S < y.F or y.S < x.F);
		};
		TwoSATsolver s(n);
		int cnt = 0;
		REP(i,n) REP(j,i){
			// DEBUG(i); DEBUG(j);
			P r1 = lr[i];
			P r2 = lr[j];
			if(intersect(r1,r2)){
				s.add_clause(-(i+1),-(j+1));
			}
			if(intersect(r1,rev(r2))){
				s.add_clause(-(i+1),(j+1));
			}
			if(intersect(rev(r1),r2)){
				s.add_clause((i+1),-(j+1));
			}
			if(intersect(rev(r1),rev(r2))){
				s.add_clause((i+1),(j+1));
			}
		}
		DEBUG(11111);
		auto ret = s.solve();
		dpite(ALL(ret));
		if(ret.size() == 0){
			cout << "NO" << endl;
		}else{
			cout << "YES" << endl;
		}
	}
	return 0;
}
0