Submission #299483

#TimeUsernameProblemLanguageResultExecution timeMemory
299483user202729Seats (IOI18_seats)C++17
33 / 100
1236 ms61172 KiB
// moreflags=grader.cpp
// subtask (H==1)
// :(
#include "seats.h"
#include<vector>
#include<climits>
#include<algorithm>
#if LOCAL
#include<iostream>
#else
#define NDEBUG
#endif
#include<cassert>

struct Tree{
	struct T{
		int minimum, count;
		T operator+(int lazy) const{return {minimum+lazy, count};}
		T operator+(T other) const{
			if(minimum<other.minimum) return *this;
			if(minimum>other.minimum) return other;
			return {minimum, count+other.count};
		}
	};
	struct Node{
		int lazy;
		T data_;
		T data() const{return data_+lazy;}
	};
	std::vector<Node> data;
	Tree(){}
	Tree(int number): data(number*2, {0, {0, 1}}){}
	// note: initial state is inconsistent (counts values of nonleafs are 1)

	void add(int left, int right, int value){
		if(left==right) return;
		assert(left<right);

		left+=int(data.size()/2); right+=int(data.size()/2);
		std::array<int, 2> const old{{left, right-1}};
		for(; left<right; left>>=1, right>>=1){
			if(left&1) data[left++].lazy+=value;
			if(right&1) data[--right].lazy+=value;
		}
		for(auto it: old){
			for(it>>=1; it; it>>=1){
				data[it].data_=data[it*2].data()+data[it*2+1].data();
			}
		}
	}

	/* // not necessary (...)
	void get(int left, int right){
		assert(left<right);
		left+=int(data.size()/2); right+=int(data.size()/2);
		for(auto it: {left, right-1}){
			for(int shift=31^__builtin_clz(it); shift; --shift){
				auto const node=it>>shift;
				if(auto const l=data[node].lazy){
					data[node].lazy=0;
					data[node].data_.minimum+=l;
					data[node*2].lazy+=l;
					data[node*2+1].lazy+=l;
				}
			}
		}

		T result{};
	}
	*/

	int get(){
		// operator+ is commutative
		auto const d=data[1].data();
		assert(d.minimum>=2);
		return d.minimum==2 ? d.count: 0;
	}
};

struct MyData{
	MyData(){}

	//int width;
	std::vector<int> value; // pos -> time (in 0..H*W), with two padded (H*W) values on the sides
	std::vector<int> R, C; // time -> pos
	Tree tree;

	MyData(int const H, int const W, std::vector<int> R_, std::vector<int> C_):
		//width(W), 
		value(W+2), 
		R(std::move(R_)), C(std::move(C_)),
		tree(W)
	{
		if(H!=1)
			std::exit(1);

		for(int time=0; time<W; ++time){
			assert(R[time]==0);
			value[C[time]+1]=time;
		}
		value[0]=value.back()=W;

		for(int i=1; i<(int)value.size(); ++i){
			auto const [a, b]=std::minmax({value[i-1], value[i]});
			tree.add(a, b, 1);
		}
	}

	int swap(int first, int sec){

		assert(value[C[first]+1]==first);
		assert(value[C[sec]+1]==sec);
		assert(R[first]==0); assert(R[sec]==0);

		std::swap(C[first], C[sec]);

		std::array<int, 4> lefts{{C[first], C[first]+1, C[sec], C[sec]+1}};
		std::sort(begin(lefts), end(lefts));
		auto const last=std::unique(begin(lefts), end(lefts));

		std::for_each(lefts.begin(), last, [&](auto const& it){
			auto const [a, b]=std::minmax({value[it], value[it+1]});
			tree.add(a, b, -1);
		});

		value[C[first]+1]=first;
		value[C[sec]+1]=sec;

		std::for_each(lefts.begin(), last, [&](auto const& it){
			auto const [a, b]=std::minmax({value[it], value[it+1]});
			tree.add(a, b, 1);
		});

		return tree.get();
	}
} myData;

void give_initial_chart(int H, int W, std::vector<int> R, std::vector<int> C) {
	myData=MyData{H, W, std::move(R), std::move(C)};
}

int swap_seats(int a, int b) {
	return myData.swap(a, b);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...