Submission #50028

#TimeUsernameProblemLanguageResultExecution timeMemory
50028shoemakerjoConstruction of Highway (JOI18_construction)C++14
100 / 100
664 ms61716 KiB
#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define maxn 100010
#define LEFT 0
#define RIGHT 1
#define pii pair<int, int>
int N;

struct node {
	node *ch[2];
	node *par;
	node *pp; //path pointer

	int sz;
	int val; //store the current value, is passed with path pointer
	int key; //just for debugging purposes, store the index for the node

	node(int vv, int kk) : val(vv), key(kk) { //sets default values
		ch[LEFT] = NULL;
		ch[RIGHT] = NULL;
		pp = NULL;
		par = NULL;
		sz = 1;
	}

	bool isroot() {
		return !par || par->ch[LEFT] != this && par->ch[RIGHT] != this;
	}

	void update() { //really only does update stuff
		sz = 1;
		if (ch[LEFT]) {
			ch[LEFT]->par = this; //why not
			sz += ch[LEFT]->sz;
		}
		if (ch[RIGHT]) {
			ch[RIGHT]->par = this;
			sz += ch[RIGHT]->sz;
		}
	}

	int getDirection() {
		if (par == NULL) return -1;
		if (this == par->ch[LEFT]) return LEFT;
		if (this == par->ch[RIGHT]) return RIGHT;
		return -1;
	}

	void setChild(int dir, node * c) {
		ch[dir] = c;
		if (c) c->par = this;
	}

	void rotateup() {
		int dir = getDirection();
		node *p = par;
		if (!p->isroot()) {
			p->par->ch[p->getDirection()] = this;
		}
		par = p->par;
		node *pMid = ch[!dir];
		p->setChild(dir, pMid);
		setChild(!dir, p);
		pp = p->pp;
		p->pp = NULL;
		val = p->val; 
		p->update();
		update();
	}

};

node *nc[maxn]; //just store some nodes b/c why not
vector<pii> cstuff; //used for counting inversions

void splay(node * x) {
	//all updates for splay should be covered in rotateup()
	x->update();
	while (!x->isroot()) {
		x->update();
		node *p1 = x->par;
		if (!p1->isroot()) {
			node *g = p1->par;
			if (p1->getDirection() == x->getDirection()) {
				p1->rotateup(); //zig zig
			}
			else x->rotateup(); // zig zag

		}
		x->rotateup();
	}

}

void access(node *x) {
	x->update();
	splay(x);
	if (x->ch[RIGHT]) {
		x->ch[RIGHT]->val = x->val;
		x->ch[RIGHT]->pp = x; //cut it off
		x->ch[RIGHT]->par = NULL;
	}
	x->ch[RIGHT] = NULL;
	x->update();
//	cout << "my stuff:  " << x->sz << endl;
	cstuff.push_back(pii(x->val, x->sz));


	while (x->pp) { //not at root of tree of aux trees yet
		node *w = x->pp;
		splay(w);

		if (w->ch[RIGHT]) {
			w->ch[RIGHT]->val = w->val;
			w->ch[RIGHT]->pp = w;
			w->ch[RIGHT]->par = NULL;
		}
		w->ch[RIGHT] = NULL; //temporary for our purposes
		w->update();
		// cout << "key line:   " << w->key << " " << w->val << " " << w->sz << endl;
		cstuff.push_back(pii(w->val, w->sz));
		w->ch[RIGHT] = x;
		x->par = w;
		x->pp = NULL;
		splay(x);
		
	}
}

int seg[maxn*4];
int nums[maxn]; //the number stored for each guy
//set up segment tree stuff
int BIT[maxn];

void update(int spot, int diff) {
	while (spot <= N) {
	//	cout << "u spot:  " << spot << endl;
		BIT[spot] += diff;
		spot += spot & (-spot);
	}
}

int query(int spot) {
	int ans = 0;
	while (spot > 0) {
	//	cout << "spot: " << spot << endl;
		ans += BIT[spot];
		spot -= spot & (-spot);
	}
	return ans;
}

/*
void up(int spot, int diff, int ss, int se, int si) {
	if (spot < ss || spot > se) return;
	if (ss == se) {
		seg[si] += diff;
		return;
	}
	int mid = (ss+se)/2;
	up(spot, diff, ss, mid, si*2+1);
	up(spot, diff, mid+1, se, si*2+2);
	seg[si] = seg[si*2+1] + seg[si*2+2];

}

void update(int spot, int diff) {
	up(spot, diff, 0, N, 0);
}

int qu(int qs, int qe, int ss, int se, int si) {
	if (qs > qe || ss > se || qs > se || qe < ss) return 0;
	if (qs <= ss && se <= qe) {
		return seg[si];
	}
	int mid = (ss+se)/2;
	return qu(qs, qe, ss, mid, si*2+1) + 
		qu(qs, qe, mid+1, se, si*2+2);
}

int query(int qs, int qe) {
	return qu(qs, qe, 0, N, 0);
}
*/

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cin >> N;
	set<int> seen;
	map<int, int> encode; //for compression
	//process each edge in order
	for (int i = 1; i <= N; i++) {
		cin >> nums[i];
		seen.insert(nums[i]);
	}
	int cv = 0;
	for (int cur : seen) {
		encode[cur] = ++cv; //want 1-indexed
	}
	for (int i = 1; i <= N; i++) {
		nums[i] = encode[nums[i]];
		nc[i] = new node(nums[i], i);
		//cout << "oval:  " << nc[i]->val << endl;
	}
	fill(BIT, BIT+maxn, 0);
	int a, b;
	for (int i = 0; i < N-1; i++) {
		cin >> a >> b; //read in edges in order
		cstuff.clear();
		ll ans = 0LL;
		access(nc[a]); //access this first guy
		//now the things in cstuff should be good to go

		//time to calculate the answer
		//reverse(cstuff.begin(), cstuff.end());
		for (pii cur : cstuff) {
			int curval = cur.first;
			int amount = cur.second;
			// cout << "something on the list: " << curval << " in count of " << amount << endl;
			ans += amount*1LL*query(curval-1); //want amount greater than me
			update(cur.first, cur.second);
		}
		for (pii cur : cstuff) {
			update(cur.first, 0-cur.second);
		}

		nc[b]->pp = nc[a];
		access(nc[b]); //run a classic access now, 
		//				this should augment my value up real nice
		nc[b]->val = nums[b]; //set the thing straight now

		cout << ans << '\n';
	}
	cin >> N;


}
//use ll b/c i think we might need it

Compilation message (stderr)

construction.cpp: In member function 'bool node::isroot()':
construction.cpp:29:40: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   return !par || par->ch[LEFT] != this && par->ch[RIGHT] != this;
                  ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
construction.cpp: In function 'void splay(node*)':
construction.cpp:85:10: warning: unused variable 'g' [-Wunused-variable]
    node *g = p1->par;
          ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...