2019百度之星复赛题解 A.B.C

1001. Diversity

题意

给你一棵n个点的树,对于节点i,你要给它标上一个 [ l i , r i ] [ l_{i}, r_{i}] [li,ri]之间的数,要求所有边两端节点上标的数字的差的绝对值的总和最大。

解法

一开始以为一边取大一边取小就会最优
其实不对 所以最后写了一遍树形DP

/* Algorithm: Author: anthony1314 Creat Time: Time Complexity: */

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef double db;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 2e5+10;

void add(int &x, int y) {
    x = (x + y) % mod;
}
ll dp[maxn][2];
vector<int> g[maxn];
ll l[maxn], r[maxn];
void dfs(int root, int x) {
    int len = g[root].size();
    for(int i = 0; i < len; i++) {
        if(g[root][i] == x) continue;
        dfs(g[root][i], root);
    }
    for(int i = 0; i < len; i++) {
        if(g[root][i] == x) continue;
        dp[root][0] += max(dp[g[root][i]][1] + abs(l[g[root][i]] - r[root]),
                           dp[g[root][i]][0] + abs(r[g[root][i]] - r[root]));
        dp[root][1] += max(dp[g[root][i]][1] + abs(l[g[root][i]] - l[root]),
                           dp[g[root][i]][0] + abs(r[g[root][i]] - l[root]));
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t, n;
    cin>>t;
    int u, v;
    while(t--) {
        for(int i = 0; i < maxn; i++) {
            g[i].clear();
        }
        memset(dp, 0, sizeof(dp));
        cin>>n;
        for(int i = 0; i < n-1; i++) {
            cin>>u>>v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
        for(int i = 1; i <= n; i++) {
            cin>>l[i]>>r[i];
        }
        dfs(1, -1);
        ll ans = -1;
        for(int i = 1; i <= n; i++){
            ans = max(ans, max(dp[i][1], dp[i][0]));
        }
        cout<<ans<<endl;
    }

    return 0;
}

1002. Transformation

题意

给你一个二元组(a,b),支持AB两种操作,分别是将其变成(a,2b−a)和(2a−b,b)。问能否通过大于等于零次操作将其变成(c,d)。

解法

答案一定满足以下规律规律:
c=((x+1)a-xb)
d=((y+1)a-yb)
那么我只要逆推回去即可
判断x和y哪个大,就用哪一种方式逆推回去

/* Algorithm: Author: anthony1314 Creat Time: Time Complexity: */

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 2000+10;

void add(int &x, int y) {
	x = (x + y) % mod;
}
stack<char> ans;
bool isOdd(ll a) {
	return a % 2;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin>>t;
	while(t--) {
		ll a, b, c, d;
		cin>>a>>b>>c>>d;
		if((a - b) == 0) {
			if(a == c && b == d) {
				printf("Yes\n\n");
			} else {
				printf("No\n");
			}
			continue;
		}
		ll x = (c - a) % (a - b);
		ll y = (d - b) % (b - a);
		if(x != 0 || y != 0) { //判断一下 c和d符不符合公式
			puts("No");
		} else {
			x = (c - a) / (a - b) + 1; // a的系数 
			y = (d - b) / (b - a) + 1; // b的系数 
			if(x <= 0 || y <= 0) {
				puts("No");
				continue;
			}
			bool f = 1;
			while(!ans.empty()){
				ans.pop();
			}
			while(c != a || b != d){
				if(isOdd(c + d)){
					f = 0;
					break;
				}
				if(x > y){
					c = (c + d) / 2;
					if(isOdd(x - (y - 1)))	{
						f = 0;
						break;
					}
					x = (x - (y - 1)) / 2;
					ans.push('B');
				}else {
					d = (c + d) / 2;
					if(isOdd(y - (x - 1)))	{
						f = 0;
						break;
					}
					y = (y - (x - 1)) / 2;
					ans.push('A');
				}
			}
			if(!f){
				puts("No");
			}else {
				puts("Yes");
				while(!ans.empty()){
					printf("%c", ans.top());
					ans.pop();
				}
				puts("");
			}
		}
	}
	return 0;
}

1003. Quasi Binary Search Tree

传送门

全部评论

相关推荐

06-12 16:00
天津大学 Java
牛客30236098...:腾讯坏事做尽,终面挂是最破防的 上次被挂了后我连简历都不刷了
点赞 评论 收藏
分享
彧未sr:查看图片
投递牧原集团等公司10个岗位
点赞 评论 收藏
分享
07-25 11:26
清华大学 Java
打开电脑,思绪又回到了7月份刚开始的时候,感觉这个月过的如梦如幻,发生了太多事,也算是丰富了我本就是平淡的人生吧太早独立的我习惯了一切都是自己做决定,拥有绝对的决定权,而且永远不会听取别人的建议。我就是那个恋爱四年出轨的男主啦,感觉既然在牛客开了这个头,那我就要做个有始有终的人。从我出轨到结束再到和女朋友和好如初真的太像一场梦了,短短的一个月我经历了太多,也成长了很多,放下了那些本就不属于我的,找回了那些我不该放弃的。我的人生丰富且多彩,但人不能一直顺,上天总会让你的生活中出点乱子,有好有坏,让你学会一些东西,让你有成长。我和女朋友的恋爱四年太过于平淡,日常除了会制造一些小浪漫之外,我们的生活...
段哥亡命职场:不得不说,我是理解你的,你能发出来足见你是个坦诚的人,至少敢于直面自己的内心和过往的过错。 这个世界没有想象中那样非黑即白,无论是农村还是城市,在看不见的阴影里,多的是这样的事。 更多的人选择站在制高点去谩骂,一方面是社会的道德是需要制高点的,另一方面,很多人不经他人苦,却劝他人善。 大部分的我们,连自己生命的意义尚且不能明晰,道德、法律、困境,众多因果交织,人会迷失在其中,只有真的走出来之后才能看明白,可是没走出来的时候呢?谁又能保证自己能走的好,走的对呢? 可是这种问题有些人是遇不到的,不去追寻,不去探寻,也就没了这些烦恼,我总说人生的意义在过程里,没了目标也就没了过程。 限于篇幅,没法完全言明,总之,这世界是个巨大的草台班子,没什么过不去了,勇敢面对,革故鼎新才是正确,祝你早日走出来。查看图片
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务