답안 #248782

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
248782 2020-07-13T11:43:42 Z user202729 새 집 (APIO18_new_home) C++17
컴파일 오류
0 ms 0 KB
#include</tmp/all.h>

struct Tree{
	std::vector<int> data;
	void reset(int number, int value){
		data.assign(number*2, value);
	}
	void changeMaximum(int left, int right, int value){
		left+=int(data.size()/2);
		right+=int(data.size()/2);
		while(left<right){
			if(left&1) { data[left]=std::max(data[left], value);++left;}
			if(right&1){ --right; data[right]=std::max(data[right], value);}
			left>>=1; right>>=1;
		}
	}
	int get(int index){
		index+=int(data.size()/2);
		int result=INT_MIN;
		for(; index; index>>=1)
			result=std::max(result, data[index]);
		return result;
	}
};

int main(){
	int numStore, numType, numQuery; cin>>numStore>>numType>>numQuery;
	struct Event{
		int position, time, type;
		bool open;
		//bool operator<(Event other) const{return time<other.time;}
	};
	std::vector<Event> events; events.reserve(numStore*2);
	for(int _=0; _<numStore; ++_){ // event before query if same time
		int position, type, open, close; cin>>position>>type>>open>>close;
		--type; assert(0<=type); assert(type<numType);
		events.push_back({position, open, type, true});
		events.push_back({position, close+1, type, false});
	}
	assert((int)events.size()==numStore*2);
	std::sort(begin(events), end(events),[&](auto first, auto sec){return first.time<sec.time;});

	struct Query{
		int position, time, index;
		bool operator<(Query other) const{return position<other.position;}
	};
	std::vector<Query> queries(numQuery);
	int numTime;

	{ // read queries & compress time
		std::vector<int> times; times.reserve(numQuery);
		for(int index=0; index<numQuery; ++index){
			auto& [position, time, index_]=queries[index];
			index_=index;
			cin>>position>>time;
			times.push_back(time);
		}
		std::sort(begin(queries), end(queries));
		std::sort(begin(times), end(times));
		times.resize(std::unique(begin(times), end(times))-begin(times));
		numTime=(int)times.size();
		for(auto& [_, time,__]: queries) time=int(std::lower_bound(begin(times), end(times), time)-begin(times));
		for(auto& event: events) event.time=int(std::lower_bound(begin(times), end(times), event.time)-begin(times));
		times.clear();
	}

	int const INFINITY=(int)4e8; //...

	struct Event1{
		int start; // inclusive (change event before query)
		bool operator<(Event1 other) const{return start<other.start;}

		int value; // or query index
		int left, right; // half inclusive. In this problem they're time. Useless for queries
	};
	std::array<std::vector<Event1>, 2> events1; // [0]: increasing,[1]: decreasing
	auto const addSegment=[&](int last, int time, int left, int right){
		assert(left<right);
		assert(last<=time); if(last==time) return;
		//assert((cout<<last<<' '<<time<<' '<<left<<' '<<right<<'\n', true));
		int const mid=(left+right)>>1;
		events1[0].push_back({mid, -left, last, time});
		events1[1].push_back({mid+1, right, last, time});
	};

	{ // construct events1
		struct Item{
			int nextLastChange;
			int count;
		};
		std::vector<std::map<int, Item>> positions(numType);
		for(auto& it: positions){ it.insert({-INFINITY, {0, 1}}); it.insert({INFINITY, {INT_MAX, 1}}); }
		// ^ I should have figured out this trick earlier...
		for(auto [position, time, type, open]: events){
			auto& map=positions[type];
			if(open){
				auto [iterator, inserted]=map.insert({position, {time, 1}});
				if(not inserted){ iterator->second.count++; continue; }
				auto const prevIterator=std::prev(iterator);
				auto const next=std::next(iterator)->first, previous=prevIterator->first;

				addSegment(prevIterator->second.nextLastChange, time, previous, next);
				// ^ if previous==-INFINITY and next==INFINITY then tree.get will be rather large
				prevIterator->second.nextLastChange=time;
				assert(iterator->second.nextLastChange==time);
			}else{
				auto iterator=map.find(position); --iterator->second.count;
				if(iterator->second.count!=0) continue;
				auto const rightLastChange=iterator->second.nextLastChange;
				auto const nextIterator=map.erase(iterator), prevIterator=std::prev(nextIterator);
				auto const next=nextIterator->first; auto const previous=prevIterator->first;

				addSegment(prevIterator->second.nextLastChange, time, previous, position);
				addSegment(rightLastChange, time, position, next);
				prevIterator->second.nextLastChange=time;
			}
		}
		int tmp=INT_MAX;
		for(auto& it: positions){
			assert(it.size()==2);
			assert(it.begin()->first==-INFINITY);
			assert(it.rbegin()->first==INFINITY);
			tmp=std::min(tmp, it.begin()->second.nextLastChange);
		}
		
		addSegment(tmp, numTime,-INFINITY, INFINITY);
	}

	// will be processed in reverse order
	std::sort(begin(events1[0]), end(events1[0]));
	std::sort(begin(events1[1]), end(events1[1]), [&](Event1 first, Event1 sec){return sec<first;});

	std::vector<int> result(numQuery, -1); // corresponds to the current index of queries

	Tree tree;
	tree.reset(numTime, -INFINITY);
	{ // process events1[0]
		for(auto index=numQuery; index--;){
			Query query=queries[index];

			while(not events1[0].empty()){
				auto [start, value, left, right]=events1[0].back();
				if(start<query.position) break;
				tree.changeMaximum(left, right, value);
				events1[0].pop_back();
			}
			//assert(tree.get(query.time)==-INFINITY or tree.get(query.time)+query.position>=0);
			result[index]=std::max(result[index], tree.get(query.time)+query.position);
		}
	}

	tree.reset(numTime, -INFINITY);
	{ // process events1[1]
		for(int index=0; index<numQuery; ++index){
			Query query=queries[index];

			while(not events1[1].empty()){
				auto [start, value, left, right]=events1[1].back();
				if(start>query.position) break;
				tree.changeMaximum(left, right, value);
				events1[1].pop_back();
			}
			//assert(tree.get(query.time)==-INFINITY or tree.get(query.time)-query.position>=0);
			result[index]=std::max(result[index], tree.get(query.time)-query.position);
		}
	}

	std::vector<int> result2(numQuery);
	for(int index=0; index<numQuery; ++index){
		result2[queries[index].index]=result[index];
	}
	for(auto cur: result2){
		assert(cur!=-1); if(cur>=INFINITY/2) cur=-1;
		cout<<cur<<'\n';
	}
}

Compilation message

new_home.cpp:1:9: fatal error: /tmp/all.h: No such file or directory
 #include</tmp/all.h>
         ^~~~~~~~~~~~
compilation terminated.