Submission #217530

#TimeUsernameProblemLanguageResultExecution timeMemory
217530mieszko11bSweeping (JOI20_sweeping)C++14
100 / 100
12479 ms257072 KiB
#include <bits/stdc++.h>
 
using namespace std;
 
using ii = pair<int, int>;
 
const int inf = 1e9 + 7;
 
#define X first
#define Y second
 
mt19937 rng(chrono::steady_clock().now().time_since_epoch().count());
 
uniform_int_distribution<int> uid(INT_MIN, INT_MAX);
 
void readint(int &a) {
	char c;
	a = 0;
	do {
		c = getchar_unlocked();
	} while(c < '0' || c > '9');
	do {
		a = a * 10 + c - '0';
		c = getchar_unlocked();
	} while(c >= '0' && c <= '9');
}
 
int rand() {
	return uid(rng);
}
 
struct SegmentTree {
	int lv;
	vector<pair<int, int> > d;
	vector<int> x;
	vector<int> ind;
	
	SegmentTree(vector<pair<int, ii>> V) {
		int n = V.size();
		lv = 2;
		while(lv < n + 2)
			lv *= 2;
		d.resize(2 * lv + 2, {inf, inf});
		x.resize(lv + 2, inf);
		ind.resize(lv + 2, inf);
		
		for(int i = 0 ; i < V.size() ; i++) {
			d[lv + i] = {V[i].Y.Y, i};
			x[i] = V[i].Y.X;
			ind[i] = V[i].X;
		}
			
		for(int i = lv - 1 ; i >= 1 ; i--)
			d[i] = min(d[2 * i], d[2 * i + 1]);
	}
	
	// ind, {x, y}
	ii _query(int a, int b) {
		if(b < a)
			return {inf, inf};
		
		int va = lv + a;
		int vb = lv + b;
		auto res = min(d[va], d[vb]);
		
		while(va / 2 != vb / 2) {
			if(va % 2 == 0)
				res = min(res, d[va + 1]);
			if(vb % 2 == 1)
				res = min(res, d[vb - 1]);
			va /= 2;
			vb /= 2;
		}
		
		return res;
	}
	
	void insert(int w, int v) {
		w += lv;
		d[w].X = v;
		w /= 2;
		while(w) {
			d[w] = min(d[2 * w], d[2 * w + 1]);
			w /= 2;
		}
	}
	
	// x <= l
	pair<int, ii> query(int l, int y) {
		auto it = upper_bound(x.begin(), x.end(), l);
		int a = 0;
		int b = distance(x.begin(), it) - 1;
		ii p = _query(a, b);
		if(p.X > y)
			return {-1, {-1, -1}};
			
		insert(p.Y, inf);
		return {ind[p.Y], {x[p.Y], p.X}};
	}
};
 
struct TreapNode {
	TreapNode *l, *r, *p;
	int x, y, q, lazyx, lazyy;
	
	TreapNode(int _x, int _y) {
		x = _x;
		y = _y;
		q = rand();
		l = r = p = nullptr;
		lazyx = 0;
		lazyy = 0;
	}
	
	TreapNode* attach(TreapNode *ll, TreapNode *rr) {
		l = ll;
		r = rr;
		if(l != nullptr)
			l->p = this;
		if(r != nullptr)
			r->p = this;
		return this;
	}
	
	void push() {
		if(!lazyx && !lazyy)
			return ;
		
		x = max(x, lazyx);
		y = max(y, lazyy);
		if(l != nullptr) {
			l->lazyx = max(l->lazyx, lazyx);
			l->lazyy = max(l->lazyy, lazyy);
		}
		
		if(r != nullptr) {
			r->lazyx = max(r->lazyx, lazyx);
			r->lazyy = max(r->lazyy, lazyy);
		}
		
		lazyx = 0;
		lazyy = 0;
	}
	
	void print() {
		push();
		cout << "[";
		if(l != nullptr)
			l->print();
		cout << "]";
		cout << "(" << x << ", " << y << ")[";
		if(r != nullptr)
			r->print();
		cout << "]";
	}
};
 
struct Treap {
	TreapNode *root;
	map<int, TreapNode*> M;
	int total;
	
	Treap() {
		root = new TreapNode(0, 0);
		total = 1;
	}
	
	~Treap() {
		for(auto p : M)
			delete p.Y;
	}
	
	TreapNode* merge(TreapNode *a, TreapNode *b) {
		if(a == nullptr)
			return b;
		if(b == nullptr)
			return a;
			
		a->push();
		b->push();
			
		if(a->q < b->q)
			return a->attach(a->l, merge(a->r, b));
		else
			return b->attach(merge(a, b->l), b->r);
	}
	
	bool comp(int x1, int y1, int x2, int y2) {
		return (x1 < x2 || y1 > y2);
	}
	
	pair<TreapNode*, TreapNode*> split(TreapNode *n, int x, int y) {
		if(n == nullptr)
			return {nullptr, nullptr};
		n->push();
		if(comp(x, y, n->x, n->y)) {
			TreapNode *m = n->l;
			n->attach(nullptr, n->r);
			auto p = split(m, x, y);
			return {p.X, n->attach(p.Y, n->r)};
		} else {
			TreapNode *m = n->r;
			n->attach(n->l, nullptr);
			auto p = split(m, x, y);
			return {n->attach(n->l, p.X), p.Y};
		}
	}
	
	void insert(int i, int x, int y) {
		TreapNode *n = new TreapNode(x, y);
		M[i] = n;
		auto p = split(root, x, y);
		root = merge(merge(p.X, n), p.Y);
		total++;
	}
	
	// dla x' <= x
	void maxy(int x, int v) {
		auto p = split(root, x, -1);
		if(p.X != nullptr)
			p.X->lazyy = max(p.X->lazyy, v);
		root = merge(p.X, p.Y);
	}
	
	// dla y' <= y
	void maxx(int y, int v) {
		auto p = split(root, inf, y+1);
		//~ cout << "maxx split" << endl;
		//~ if(p.X != nullptr) p.X->print(); cout << endl;
		//~ if(p.Y != nullptr) p.Y->print(); cout << endl;
		if(p.Y != nullptr)
			p.Y->lazyx = max(p.Y->lazyx, v);
		root = merge(p.X, p.Y);
	}
	
	void process_lazy_up(TreapNode *n) {
		if(n == nullptr)
			return ;
		process_lazy_up(n->p);
		n->push();
	}
	
	ii query(int i) {
		TreapNode *n = M[i];
		process_lazy_up(n);
		return {n->x, n->y};
	}
	
	void print() {
		root->print();
		cerr << endl;
	}
	
	void push(TreapNode *n) {
		if(n == nullptr)
			return ;
		n->push();
		push(n->l);
		push(n->r);
	}
	
	vector<pair<int, ii> > pushall() {
		push(root);
		vector<pair<int, ii> > res;
		res.reserve(total);
		for(auto p : M)
			res.push_back({p.X, {p.Y->x, p.Y->y}});
		return res;
	}
};
 
struct Points {
	// inicjalizujemy punktami, ktore sie nie zmieniaja
	// wrzucamy wszystkie na drzewo i mape wektorow
	// treap pusty
	// przy kazdym zapytaniu najpierw aktualizujemy treapa, potem przerzucamy na niego punkty
	
	int n, m;
	Treap *T;
	SegmentTree *ST;
	set<int> on_treap;
	map<int, ii> initial_cor;
	
	static bool compp(const pair<int, ii> &a, const pair<int, ii> &b) {
		return a.Y.X < b.Y.X;
	}
	
	Points(vector<pair<int, ii> > &P, int n) {
		this->n = n;
		T = new Treap();

		m = P.size();
		sort(P.begin(), P.end(), compp);
		ST = new SegmentTree(P);
		for(auto p : P)
			initial_cor[p.X] = p.Y;
	}
	
	~Points() {
		delete T;
		delete ST;
	}
	
	ii query(int i) {
		if(on_treap.count(i))
			return T->query(i);
		else
			return initial_cor[i];
	}
	
	void sweep_horizontally(int s) {
		T->maxx(s, n - s);
		pair<int, ii> p;
		while((p = ST->query(n - s, s)).X != -1) {
			T->insert(p.X, n - s, p.Y.Y);
			on_treap.insert(p.X);
		}
	}
	
	void sweep_vertically(int s) {
		T->maxy(s, n - s);
		pair<int, ii> p;
		while((p = ST->query(s, n - s)).X != -1) {
			T->insert(p.X, p.Y.X, n - s);
			on_treap.insert(p.X);
		}
	}
	
	int size() {
		return m;
	}
	
	vector<pair<int, ii> > get_all_points() {
		vector<pair<int, ii>> res = T->pushall();
		for(auto p : initial_cor) {
			if(!on_treap.count(p.X))
				res.push_back({p.X, p.Y});
		}
		return res;
	}
};
 
struct MasterPoints {
	int n;
	Points *I;
	vector<Points*> P;
	map<int, Points*> M;
	
	MasterPoints(vector<pair<int, ii> > &P, int n) {
		this->n = n;
		I = new Points(P, n);
		for(auto p : P)
			M[p.X] = I;
	}
	
	ii query(int i) {
		return M[i]->query(i);
	}
	
	void sweep_horizontally(int s) {
		I->sweep_horizontally(s);
		for(auto p : P)
			p->sweep_horizontally(s);
	}
	
	void sweep_vertically(int s) {
		I->sweep_vertically(s);
		for(auto p : P)
			p->sweep_vertically(s);
	}
	
	void add_point(int i, int x, int y) {
		vector<pair<int, ii> > PPP;
		PPP.push_back({i, {x, y}});
		while(P.size() && P.back()->size() == PPP.size()) {
			auto P1 = P.back()->get_all_points();
			delete P.back();
			P.pop_back();
			for(auto p : P1)
				PPP.push_back(p);
		}
		
		P.push_back(new Points(PPP, n));
		for(auto p : PPP)
			M[p.X] = P.back();
		//~ cerr << P.size() << endl;
	}
};
 
int n, m, q;
MasterPoints *PP;
 
int main() {
	//~ scanf("%d%d%d", &n, &m, &q);
	readint(n);
	readint(m);
	readint(q);
 
	vector<pair<int, ii> > P;
	for(int i = 1 ; i <= m ; i++) {
		int a, b;
		//~ scanf("%d%d", &a, &b);
		readint(a);
		readint(b);
		P.push_back({i, {a, b}});
	}
	
	PP = new MasterPoints(P, n);
 
	int cnt = m;
	while(q--) {
		//~ cout << q << endl;
		int t;
		//~ scanf("%d", &t);
		readint(t);
		if(t == 1) {
			int i;
			//~ scanf("%d", &i);
			readint(i);
			ii p = PP->query(i);
			printf("%d %d\n", p.X, p.Y);
		} else if(t == 2) {
			int s;
			//~ scanf("%d", &s);
			readint(s);
			PP->sweep_horizontally(s);
		} else if(t == 3) {
			int s;
			//~ scanf("%d", &s);
			readint(s);
			PP->sweep_vertically(s);
		} else {
			int a, b;
			//~ scanf("%d%d", &a, &b);
			readint(a);
			readint(b);
			PP->add_point(++cnt, a, b);
		}
		
		//~ cout << "TREAP\n";
		//~ PP->T->print();
	}
 
	return 0;
}

Compilation message (stderr)

sweeping.cpp: In constructor 'SegmentTree::SegmentTree(std::vector<std::pair<int, std::pair<int, int> > >)':
sweeping.cpp:47:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i = 0 ; i < V.size() ; i++) {
                   ~~^~~~~~~~~~
sweeping.cpp: In member function 'void MasterPoints::add_point(int, int, int)':
sweeping.cpp:375:38: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   while(P.size() && P.back()->size() == PPP.size()) {
                     ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
#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...