列表

详情


NC15480. Tommy 的结合

描述

人生大概就是这样。在这物欲横流的红尘紫陌中,芸芸众生为了生计四处奔走,交谈越来越少,感情越来越淡。但是,著名科学家 Access Globe 的最新研究成果可以解决这样的问题:通过增加同时做的事情来增加共同语言。
A 和 B 都得到了一些任务,设他们要执行的任务集合分别为 VA 和 VB。对每个人来说,任务 1 是必须一开始做的,而其他的每个任务 e 都存在一个前置任务 pe,表示任务 e 必须在任务 pe 完成后才能执行。也就是说,每个人的任务的依赖关系构成了一棵有根外向树,一个任务 e 能被执行当且仅当 pe,ppe,...,1 这些任务全部都被执行,称 p 依赖任务 pe,ppe,...,1 
现在,A 和 B 希望他们能有一些任务是共同完成的,因此他们决定这样选出一些任务:A 选出 m 个任务 a1,...,am,要求 a1=1,并且对于任意的 1≤ i<m,都要求 ai+1依赖任务 ai;同时 B 也选出 m 个满足同样要求的任务 b1,...,bm,这样,A 就可以沿着从 1 到 Am 的路径依次执行这些任务,同时 B 也可以沿着 1 到 Bm 的路径依次执行这些任务;并且经过安排,当 A 在执行任务 ai 的时候,B 恰好在执行任务 bi,在这时 A 和 B 就能取得联系,增进感情。

模型的目标为最大化亲密度。对于一组同时执行任务的关系 ai 和 bi,可以获得 Cai,bi的得分;同时,A 和 B 一旦失去联系,就会使得亲密度降低,在每一分钟,如果一方距离上次和对方联系后已经执行任务 i 分钟,就会使得亲密度降低 2i-1。

例如,两个人要做的任务所花费的时间分别为 2,1,4,7 和 4,8,3,6,4,并且共同完成了第一个任务和最后一个任务,那么 A 在执行中间两个任务的 1+4=5 分钟没有和 B 联系,使得亲密度降低 1+3+...+11=25;同时 B 在执行中间三个任务的 8+3+6=17 分钟没有和 A 联系,使得亲密度降低 1+3+...+35=289。注意,亲密度的计算只和任务执行的时间有关;并且任意两个任务都可以作为 ai 和 bi 同时执行,不需要保证它们花费的时间相同。

现在,给出 A 和 B 的任务、依赖关系和每个任务的执行时间,请你帮我们求出能够获得的最大的亲密度。

输入描述

第一行两个整数 |VA|,|VB|;
第二行|VA|-1 个整数 ,表示 A 的每个任务的时间长度;
第三行 |VA|-1 个整数,表示 B 的每个任务的时间长度;
第四行 |VA|-1 个整数,表示 A 的每个任务的前置任务,保证
第五行 |VB|-1 个整数 ,表示 B 的每个任务的前置任务,保证
接下来 |VA|-1 行,每行 |VB|-1 个整数,第 i-1 行第 j-1 列为 Ci,j,表示 A 和 B 同时分别执行对应的任务 i, j 能获得的亲密度,注意这些亲密度不一定是非负的;
注意以上输入均不包括第 1 个任务的信息,因为它和亲密度的计算没有关系。

输出描述

输出能获得的最大的亲密度。

示例1

输入:

5 4
2 1 2 1
1 1 1
1 2 3 4
1 2 2
-8 -1 6
4 -3 7
-7 5 5
-7 5 -5

输出:

5

说明:

A 和 B 分别选出任务 1,3,4 和 1,2,3,同时执行的任务对 (1,1)、(3,2) 和 (4,3) 使得他们获得了 4+5=9 的亲密度;A 孤独地执行任务 2 的 2 分钟丢失了 1+3=4 的亲密度,因此最终的总亲密度为 9-4=5。这就是亲密度最大的方案。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 223ms, 内存消耗: 53728K, 提交时间: 2018-04-05 17:27:52

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <cstdlib>

namespace __board_lovable__ {
	
	using ll = long long;
	const int MAX_N = 2777;
	constexpr ll sqr(ll x) {return x * x;}

	int na, nb;
	int pa[MAX_N], pb[MAX_N], ta[MAX_N], tb[MAX_N];
	int adja[MAX_N], nxta[MAX_N], adjb[MAX_N], nxtb[MAX_N];

	struct Point {
		int x; ll y;
		inline double operator * (const Point& p) const {
			return double(y - p.y) / (x - p.x);
		}
	};

	struct Hull {
		Point q[MAX_N]; 
		double k[MAX_N];
		struct Backup {
			int l, r; Point p; double k;
		}	bak[MAX_N << 1];
		int l, r, top;
		inline void clear() { l = 1; r = 0; top = 0; k[1] = 1.0 / 0.0;}
		inline void add(Point p) {
			bak[++top].l = -1;
			bak[top].r = r;
			if(l > r || k[r] > q[r] * p) ++r;
			else {
				int ll = l, rr = r, mm;
				while(ll < rr) {
					mm = (ll + rr) >> 1;
					(k[mm] <= q[mm] * p) ? rr = mm : ll = mm + 1;
				}
				r = ll;
			}
			bak[top].p = q[r];
			bak[top].k = k[r];
			q[r] = p;
			if(l < r) k[r] = p * q[r - 1]; else k[r] = 1.0 / 0.0;
		}
		inline ll query(int _k) {
			bak[++top].l = l;
			bak[top].r = -1;
			int ll = l, rr = r, mm;
			while(ll < rr) {
				mm = (ll + rr + 1) >> 1;
				k[mm] >= _k ? ll = mm : rr = mm - 1;
			}
			l = ll;
			return q[l].y - (long long) _k * q[l].x;
		}
		inline void restore(int old) {
			for(; top > old; --top) {
				if(bak[top].l == -1) {
					q[r] = bak[top].p;
					k[r] = bak[top].k;
					r = bak[top].r;
				}
				else l = bak[top].l; 
			}
		}
	}	Qf[MAX_N], Qg;
	
	int AA, AA1, BB, BB1, val[MAX_N][MAX_N], *C;
	ll F, G, ans = -(1ll << 60);

	void dfs_b(int p) {
		int old = Qg.top;
		BB = tb[p]; BB1 = tb[pb[p]];
		F = Qf[p].query(-(AA1 << 1)) - sqr(AA1) + C[p];
		if(pb[p] != 1) G = Qg.query(-(BB1 << 1)) - sqr(BB1);
		Qg.add({BB, F - sqr(BB)});
		if(pb[p] != 1) Qf[p].add({AA, G - sqr(AA)});
		if(ans < F) ans = F;
		for(int k = adjb[p]; k; k = nxtb[k]) dfs_b(k);
		Qg.restore(old);

	}
	void dfs_a(int p) {
		AA = ta[p]; AA1 = ta[pa[p]]; C = val[p];
		Qg.clear();
		static int _old[MAX_N][MAX_N]; 
		int *old = _old[p];
		for(int k = 2; k <= nb; ++k) old[k] = Qf[k].top;
		for(int k = adjb[1]; k; k = nxtb[k]) dfs_b(k);
		for(int k = adja[p]; k; k = nxta[k]) dfs_a(k);
		for(int k = 2; k <= nb; ++k) Qf[k].restore(old[k]);
	}

	char buff[1 << 27], *S = buff;
	int next_int() {
		while((*S < '0' || *S > '9') && *S != '-')	++S;
		bool neg = (*S == '-' ? ++S : 0); int ret = 0;
		while('0' <= *S && *S <= '9') ret = ret * 10 + *(S++) - '0';
		return neg ? -ret : ret;
	}

	void __main__() {
		if(!fread(buff, 1, 1 << 27, stdin)) exit(-1);
		na = next_int(); nb = next_int();
		for(int i = 2; i <= na; ++i) ta[i] = next_int();
		for(int i = 2; i <= nb; ++i) tb[i] = next_int();
		for(int i = 2; i <= na; ++i) {pa[i] = next_int(); ta[i] += ta[pa[i]]; nxta[i] = adja[pa[i]]; adja[pa[i]] = i;}
		for(int i = 2; i <= nb; ++i) {pb[i] = next_int(); tb[i] += tb[pb[i]]; nxtb[i] = adjb[pb[i]]; adjb[pb[i]] = i;}
		for(int i = 2; i <= na; ++i) for(int j = 2; j <= nb; ++j) val[i][j] = next_int();

		for(int i = 2; i <= nb; ++i) {Qf[i].clear(); Qf[i].add({0, -sqr(tb[pb[i]])});}
		for(int k = adja[1]; k; k = nxta[k]) dfs_a(k);

		std::cout << ans << std::endl;
	}
}

int main() {
	std::ios::sync_with_stdio(0);
	std::cin.tie(0); std::cout.tie(0);
	__board_lovable__::__main__();
}

上一题