2015上海區域賽D題 左偏樹+樹形DP

花費大約半星期時間終於做出來了. 這道題細節很多. 註釋和思路之類的之後補充,現在太累辣!

題目鏈接:點擊打開鏈接

代碼如下:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<iomanip>
#include<stdlib.h>
#include<cstdio>
#include<string>
#include<string.h>
#include<set>
#include<stack>
#include<map>
using namespace std;

#define rep(i, n) for(int i=0; i<n ;i++)
#define Rep(i, n) for(int i=1; i<=n; i++)
#define SYS system("pause");
typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x7fffffff;
const int MAX_N = 2e5 + 5;
const int MAX_V = 0;
const int MAX_M = 0;
const int MAX_Q = 0;

int l[MAX_N], r[MAX_N], dist[MAX_N];
int N, M;
P query[MAX_N], ban[MAX_N];
int par[MAX_N], in[MAX_N];
vector<P> s;

int merge(int a, int b) {
	if (!a) return b;
	if (!b) return a;
	if (query[a].first > query[b].first)  swap(a, b);
	r[a] = merge(r[a], b);
	if (dist[r[a]] > dist[l[a]]) swap(l[a], r[a]);
	if (!r[a]) dist[a] = 0;
	else dist[a] = dist[r[a]] + 1;
	return a;
}
struct node {
	int qe, h, out, in;
}nd[MAX_N];

int root(int x) {
	return par[x] == x ? x : par[x] = root(par[x]);
}

void init() {
	memset(l, 0, sizeof l);
	memset(r, 0, sizeof r);
	memset(dist, 0, sizeof dist);

	Rep(i, N) {
		par[i] = i;
		nd[i].h = nd[i].in = nd[i].out = nd[i].qe = 0;
	}
	Rep(i, M) nd[in[i]].qe = merge(nd[in[i]].qe, i);
}

void get_up(int id, int he) {
	int in_max=0, out_max=0, tmp = 0;
	s.clear();
	while (nd[id].qe && query[nd[id].qe].first < he) {
		if (query[nd[id].qe].second == 0) in_max++;
		s.push_back(query[nd[id].qe]);
		nd[id].qe = merge(l[nd[id].qe], r[nd[id].qe]);
	}
	tmp = out_max = in_max;
	for (int i = 0; i < s.size(); i++) {
		if (i && s[i].first != s[i - 1].first) {
			out_max = max(tmp, out_max);
		}
		s[i].second == 0 ? tmp-- : tmp++;
	}
	out_max = max(out_max, tmp);
	nd[id].in = max(nd[id].in + in_max, nd[id].out + out_max);
	nd[id].out += tmp;
	nd[id].h = he;
}

void Merge(int p1, int p2, int he) {
	p1 = root(p1);
	p2 = root(p2);
	if(nd[p1].h<he)get_up(p1, he);
	if(nd[p2].h<he)get_up(p2, he);
	nd[p1].qe = merge(nd[p1].qe, nd[p2].qe);
	par[p2] = p1;
	nd[p1].in = nd[p1].in + nd[p2].in;
	nd[p1].out = nd[p1].out + nd[p2].out;
}

void solve() {
	init();
	sort(ban + 1, ban + N);
	Rep(i, N - 1) {
		Merge(ban[i].second, ban[i].second + 1, ban[i].first);
	}
	int final = root(1);
	get_up(final, 1e9 + 7);
	cout << nd[final].in << endl;
}

int main() {
	int T,Case=0; cin >> T;
	while (T--) {
		cin >> N >> M;
		Rep(i, N - 1) {
			scanf("%d", &ban[i].first);
			ban[i].second = i;
		}
		Rep(i, M) {
			scanf("%d%d%d", &in[i], &query[i].first, &query[i].second);
		}
		cout << "Case #" << ++Case << ": ";
		solve();
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章