Submission #372589


Source Code Expand

#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <cctype>
#include <cassert>
#include <limits>
#include <functional>
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
#if defined(_MSC_VER) || __cplusplus > 199711L
#define aut(r,v) auto r = (v)
#else
#define aut(r,v) __typeof(v) r = (v)
#endif
#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#define mset(m,v) memset(m,v,sizeof(m))
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
using namespace std;
typedef vector<int> vi; typedef pair<int,int> pii; typedef vector<pair<int,int> > vpii; typedef long long ll;
template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }
template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }


struct Xor128 {
	unsigned x, y, z, w;
	Xor128(): x(123456789), y(362436069), z(521288629), w(88675123) { }
	unsigned next() {
		unsigned t = x ^ (x << 11);
		x = y; y = z; z = w;
		return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
	}
	//手抜き
	inline unsigned next(unsigned n) { return next() % n; }
};

//bottom upなTreap
//脱再帰!
//randomized binary searchにするにはchoiceRandomlyを
//	bool choiceRandomly(Ref l, Ref r) { return rng.next(l->size + r->size) < l->size; }
//に書き換えるだけでよい。
template<typename Node>
struct BottomupTreap {
	Xor128 rng;
	typedef Node *Ref;
	static int size(Ref t) { return !t ? 0 : t->size; }

	unsigned nextRand() { return rng.next(); }
private:
	bool choiceRandomly(Ref l, Ref r) {
		return l->priority < r->priority;
	}
public:

	Ref join(Ref l, Ref r) {
		if(!l) return r;
		if(!r) return l;

		Ref t = NULL;
		unsigned long long dirs = 0;
		int h;
		for(h = 0; ; ++ h) {
			if(h >= sizeof(dirs)*8 - 2) {
				//dirsのオーバーフローを防ぐために再帰する。
				//あくまでセーフティガードなのでバランスは多少崩れるかもしれない
				t = join(l->right, r->left);
				dirs = dirs << 2 | 1;
				h ++;
				break;
			}
			dirs <<= 1;
			if(choiceRandomly(l, r)) {
				Ref c = l->right;
				if(!c) {
					t = r;
					r = r->parent;
					break;
				}
				l = c;
			}else {
				dirs |= 1;
				Ref c = r->left;
				if(!c) {
					t = l;
					l = l->parent;
					break;
				}
				r = c;
			}
		}
		for(; h >= 0; -- h) {
			if(!(dirs & 1)) {
				Ref p = l->parent;
				t = l->linkr(t);
				l = p;
			}else {
				Ref p = r->parent;
				t = r->linkl(t);
				r = p;
			}
			dirs >>= 1;
		}
		return t;
	}

	typedef std::pair<Ref,Ref> RefPair;

	//l<t≦rの(l,r)に分割する
	RefPair split2(Ref t) {
		Ref p, l = t->left, r = t;
		Node::cut(l); t->linkl(NULL);
		while(p = t->parent) {
			t->parent = NULL;
			if(p->left == t)
				r = p->linkl(r);
			else
				l = p->linkr(l);
			t = p;
		}
		return RefPair(l, r);
	}
	//l<t<rの(l,t,r)に分割する。(l,r)を返す
	RefPair split3(Ref t) {
		Ref p, l = t->left, r = t->right;
		Node::cut(l), Node::cut(r);
		t->linklr(NULL, NULL);
		while(p = t->parent) {
			t->parent = NULL;
			if(p->left == t)
				r = p->linkl(r);
			else
				l = p->linkr(l);
			t = p;
		}
		return RefPair(l, r);
	}
	Ref cons(Ref h, Ref t) {
		assert(size(h) == 1);
		if(!t) return h;
		Ref u = NULL;
		while(true) {
			if(choiceRandomly(h, t)) {
				Ref p = t->parent;
				u = h->linkr(t);
				t = p;
				break;
			}
			Ref l = t->left;
			if(!l) {
				u = h;
				break;
			}
			t = l;
		}
		while(t) {
			u = t->linkl(u);
			t = t->parent;
		}
		return u;
	}
};

class EulerTourTree {
	struct Node {
		typedef BottomupTreap<Node> BST;

		Node *left, *right, *parent;
		int size;
		unsigned priority;
		pair<int,int> val, mini;

		Node(): left(NULL), right(NULL), parent(NULL),
			size(1), priority(0), val(mp(INF, INF)), mini(mp(INF, INF)) { }

		inline Node *update() {
			int size_t = 1; pair<int,int> mini_t = val;
			if(left) {
				size_t += left->size;
				amin(mini_t, left->mini);
			}
			if(right) {
				size_t += right->size;
				amin(mini_t, right->mini);
			}
			size = size_t, mini = mini_t;
			return this;
		}

		inline Node *linkl(Node *c) {
			if(left = c) c->parent = this;
			return update();
		}
		inline Node *linkr(Node *c) {
			if(right = c) c->parent = this;
			return update();
		}
		inline Node *linklr(Node *l, Node *r) {
			if(left = l) l->parent = this;
			if(right = r) r->parent = this;
			return update();
		}
		static Node *cut(Node *t) {
			if(t) t->parent = NULL;
			return t;
		}

		static const Node *findRoot(const Node *t) {
			while(t->parent) t = t->parent;
			return t;
		}
		static std::pair<Node*,int> getPosition(Node *t) {
			int k = BST::size(t->left);
			Node *p;
			while(p = t->parent) {
				if(p->right == t)
					k += BST::size(p->left) + 1;
				t = p;
			}
			return std::make_pair(t, k);
		}
		static const Node *findHead(const Node *t) {
			while(t->left) t = t->left;
			return t;
		}
		static void updatePath(Node *t) {
			while(t) {
				t->update();
				t = t->parent;
			}
		}
	};

	typedef Node::BST BST;
	BST bst;

	std::vector<Node> nodes;
	//各頂点に対してその頂点から出ているarcを1つだけ代表として持つ(無い場合は-1)
	//逆にarcに対して対応する頂点はたかだか1つである
	std::vector<int> firstArc;

	inline int getArcIndex(const Node *a) const { return a - &nodes[0]; }

	inline int arc1(int ei) const { return ei; }
	inline int arc2(int ei) const { return ei + (numVertices() - 1); }

public:
	inline int numVertices() const { return firstArc.size(); }
	inline int numEdges() const { return numVertices() - 1; }
private:

	void updateMarks(int a, int v) {
		//nothing
	}

	//firstArcの変更に応じて更新する
	void firstArcChanged(int v, int a, int b) {
		if(a != -1) updateMarks(a, -1);
		if(b != -1) updateMarks(b, v);
	}

public:
	class TreeRef {
		friend class EulerTourTree;
		const Node *ref;
	public:
		TreeRef() { }
		TreeRef(const Node *ref_): ref(ref_) { }
		bool operator==(const TreeRef &that) const { return ref == that.ref; }
		bool operator!=(const TreeRef &that) const { return ref != that.ref; }
		bool isIsolatedVertex() const { return ref == NULL; }
	};

	void init(int N) {
		int M = N - 1;
		firstArc.assign(N, -1);
		nodes.assign(M * 2, Node());
		for(int i = 0; i < M * 2; i ++)
			nodes[i].priority = bst.nextRand();
	}

	TreeRef getTreeRef(int v) const {
		int a = firstArc[v];
		return TreeRef(a == -1 ? NULL : Node::findRoot(&nodes[a]));
	}

	bool isConnected(int v, int w) const {
		if(v == w) return true;
		int a = firstArc[v], b = firstArc[w];
		if(a == -1 || b == -1) return false;
		return Node::findRoot(&nodes[a]) == Node::findRoot(&nodes[b]);
	}

	int getTreeFirstArc(TreeRef t) const {
		assert(!t.isIsolatedVertex());
		return getArcIndex(t.ref);
	}

	static int getSize(TreeRef t) {
		if(t.isIsolatedVertex()) return 1;
		else return t.ref->size / 2 + 1;
	}

	static pair<int,int> getMini(TreeRef t) {
		assert(!t.isIsolatedVertex());
		return t.ref->mini;
	}

	void link(int ti, int v, int w) {
		int a1 = arc1(ti), a2 = arc2(ti);
		//v→wがa1に対応するようにする
		if(v > w) std::swap(a1, a2);

		int va = firstArc[v], wa = firstArc[w];

		Node *l, *m, *r;
		if(va != -1) {
			//evert。順番を入れ替えるだけ
			std::pair<Node*,Node*> p = bst.split2(&nodes[va]);
			m = bst.join(p.second, p.first);
		}else {
			//vが孤立点の場合
			m = NULL;
			firstArc[v] = a1;
			firstArcChanged(v, -1, a1);
		}
		if(wa != -1) {
			std::pair<Node*,Node*> p = bst.split2(&nodes[wa]);
			l = p.first, r = p.second;
		}else {
			//wが孤立点の場合
			l = r = NULL;
			firstArc[w] = a2;
			firstArcChanged(w, -1, a2);
		}
		//w→vの辺をmの先頭=lの末尾にinsert
		m = bst.cons(&nodes[a2], m);
		//v→wの辺をmの末尾=rの先頭にinsert
		r = bst.cons(&nodes[a1], r);

		bst.join(bst.join(l, m), r);
	}

	void cut(int ti, int v, int w) {
		//v→wがa1に対応するようにする
		if(v > w) std::swap(v, w);

		int a1 = arc1(ti), a2 = arc2(ti);
		std::pair<Node*,Node*> p = bst.split3(&nodes[a1]);
		int prsize = BST::size(p.second);
		std::pair<Node*,Node*> q = bst.split3(&nodes[a2]);
		Node *l, *m, *r;
		//a1,a2の順番を判定する。a1<a2ならp.secondが変わっているはず
		if(p.second == &nodes[a2] || BST::size(p.second) != prsize) {
			l = p.first, m = q.first, r = q.second;
		}else {
			//a2<a1の順番である。v→wの辺がa1であって親→子であることにする
			std::swap(v, w);
			std::swap(a1, a2);
			l = q.first, m = q.second, r = p.second;
		}

		//firstArcを必要に応じて書き換える
		if(firstArc[v] == a1) {
			int b;
			if(r != NULL) {
				//vが根じゃないなら右側の最初の辺でよい
				b = getArcIndex(Node::findHead(r));
			}else {
				//vが根なら最初の辺でよい。孤立点になるなら-1
				b = !l ? -1 : getArcIndex(Node::findHead(l));
			}
			firstArc[v] = b;
			firstArcChanged(v, a1, b);
		}
		if(firstArc[w] == a2) {
			//wが根になるので最初の辺でよい。孤立点になるなら-1
			int b = !m ? -1 : getArcIndex(Node::findHead(m));
			firstArc[w] = b;
			firstArcChanged(w, a2, b);
		}

		bst.join(l, r);
	}

	void changeEdgeValue(int ti, pair<int,int> x) {
		assert(ti < numEdges());
		Node *t = &nodes[ti];
		t->val = x;
		Node::updatePath(t);
	}

	pair<int,int> getEdgeValue(int ti) const {
		assert(ti < numEdges());
		const Node *t = &nodes[ti];
		return t->val;
	}
};

int main() {
	int N;
	scanf("%d", &N);
	vector<pii> edges(N-1);
	EulerTourTree ett; ett.init(N);
	rep(i, N-1) {
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c), -- a, -- b;
		edges[i] = mp(a, b);
		ett.changeEdgeValue(i, mp(c, i));
		ett.link(i, a, b);
	}
	vector<bool> deleted(N-1, false);
	int Q;
	scanf("%d", &Q);
	rep(ii, Q) {
		int ty;
		scanf("%d", &ty);
		if(ty == 1) {
			int i, d;
			scanf("%d%d", &i, &d), -- i;
			if(!deleted[i]) {
				pii p = ett.getEdgeValue(i);
				ett.changeEdgeValue(i, mp(p.first + d, p.second));
			}
		}else {
			int i;
			scanf("%d", &i), -- i;
			if(deleted[i]) {
				puts("-1");
			}else {
				EulerTourTree::TreeRef t = ett.getTreeRef(edges[i].first);
				assert(!t.isIsolatedVertex());
				pii p = ett.getMini(t);
				int j = p.second;
				printf("%d\n", j + 1);
				ett.cut(j, edges[j].first, edges[j].second);
				deleted[j] = true;
			}
		}
	}
	return 0;
}

Submission Info

Submission Time
Task I - 盆栽
User anta
Language C++ (GCC 4.9.2)
Score 300
Code Size 11148 Byte
Status AC
Exec Time 416 ms
Memory 11416 KB

Compile Error

./Main.cpp: In function ‘int main()’:
./Main.cpp:415:17: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d", &N);
                 ^
./Main.cpp:420:42: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%d%d", &a, &b, &c), -- a, -- b;
                                          ^
./Main.cpp:427:17: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d", &Q);
                 ^
./Main.cpp:430:19: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d", &ty);
                   ^
./Main.cpp:433:31: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
    scanf("%d%d", &i, &d), ...

Judge Result

Set Name Subtask All
Score / Max Score 30 / 30 270 / 270
Status
AC × 17
AC × 50
Set Name Test Cases
Subtask atetubou-challenge1.in, subtask_00.txt, subtask_01.txt, subtask_02.txt, subtask_03.txt, subtask_04.txt, subtask_05.txt, subtask_06.txt, subtask_07.txt, subtask_08.txt, subtask_09.txt, subtask_10.txt, subtask_11.txt, subtask_12.txt, subtask_13.txt, subtask_14.txt, subtask_15.txt, subtask_16.txt
All scrambled_00.txt, scrambled_01.txt, scrambled_02.txt, scrambled_03.txt, scrambled_04.txt, scrambled_05.txt, scrambled_06.txt, scrambled_07.txt, scrambled_08.txt, scrambled_09.txt, scrambled_10.txt, scrambled_11.txt, scrambled_12.txt, scrambled_13.txt, scrambled_14.txt, scrambled_15.txt, scrambled_16.txt, scrambled_17.txt, scrambled_18.txt, scrambled_19.txt, scrambled_20.txt, scrambled_21.txt, scrambled_22.txt, scrambled_23.txt, scrambled_24.txt, scrambled_25.txt, scrambled_26.txt, scrambled_27.txt, scrambled_28.txt, scrambled_29.txt, scrambled_30.txt, scrambled_31.txt, scrambled_32.txt, subtask_00.txt, subtask_01.txt, subtask_02.txt, subtask_03.txt, subtask_04.txt, subtask_05.txt, subtask_06.txt, subtask_07.txt, subtask_08.txt, subtask_09.txt, subtask_10.txt, subtask_11.txt, subtask_12.txt, subtask_13.txt, subtask_14.txt, subtask_15.txt, subtask_16.txt
Case Name Status Exec Time Memory
scrambled_00.txt AC 25 ms 800 KB
scrambled_01.txt AC 27 ms 800 KB
scrambled_02.txt AC 28 ms 800 KB
scrambled_03.txt AC 25 ms 928 KB
scrambled_04.txt AC 26 ms 928 KB
scrambled_05.txt AC 26 ms 928 KB
scrambled_06.txt AC 26 ms 924 KB
scrambled_07.txt AC 27 ms 920 KB
scrambled_08.txt AC 27 ms 928 KB
scrambled_09.txt AC 26 ms 804 KB
scrambled_10.txt AC 25 ms 796 KB
scrambled_11.txt AC 411 ms 11296 KB
scrambled_12.txt AC 412 ms 11300 KB
scrambled_13.txt AC 407 ms 11416 KB
scrambled_14.txt AC 394 ms 11300 KB
scrambled_15.txt AC 396 ms 11292 KB
scrambled_16.txt AC 413 ms 11292 KB
scrambled_17.txt AC 412 ms 11292 KB
scrambled_18.txt AC 416 ms 11292 KB
scrambled_19.txt AC 410 ms 11304 KB
scrambled_20.txt AC 405 ms 11296 KB
scrambled_21.txt AC 253 ms 11304 KB
scrambled_22.txt AC 27 ms 800 KB
scrambled_23.txt AC 24 ms 920 KB
scrambled_24.txt AC 26 ms 924 KB
scrambled_25.txt AC 27 ms 924 KB
scrambled_26.txt AC 27 ms 928 KB
scrambled_27.txt AC 271 ms 11292 KB
scrambled_28.txt AC 275 ms 11300 KB
scrambled_29.txt AC 277 ms 11304 KB
scrambled_30.txt AC 274 ms 11300 KB
scrambled_31.txt AC 275 ms 11296 KB
scrambled_32.txt AC 23 ms 924 KB
subtask_00.txt AC 27 ms 928 KB
subtask_01.txt AC 26 ms 920 KB
subtask_02.txt AC 27 ms 932 KB
subtask_03.txt AC 27 ms 804 KB
subtask_04.txt AC 27 ms 796 KB
subtask_05.txt AC 24 ms 928 KB
subtask_06.txt AC 27 ms 860 KB
subtask_07.txt AC 27 ms 928 KB
subtask_08.txt AC 27 ms 808 KB
subtask_09.txt AC 27 ms 860 KB
subtask_10.txt AC 26 ms 928 KB
subtask_11.txt AC 27 ms 928 KB
subtask_12.txt AC 27 ms 924 KB
subtask_13.txt AC 27 ms 864 KB
subtask_14.txt AC 27 ms 796 KB
subtask_15.txt AC 25 ms 808 KB
subtask_16.txt AC 25 ms 804 KB