蓝桥杯普及模拟赛 C[01背包变形] & D[树边多次统计]
C. 春季特惠
描述
JM编程平台的春季特惠开始了,你决定购买一些编程课程。
现在你一共有X元的预算,该平台上所有的n个课程均有折扣,标号为i的课程的原价a_i元,现价只要b_i元(也就是说该课程可以优惠a_i-b_i元)并且你购买该课程能获得充实值为w_i。
由于优惠的存在,你可能做出一些冲动消费导致最终买课程的总费用超过预算,但只要满足获得的总优惠金额不低于超过预算的总金额,那在心理上就不会觉得吃亏。
现在你希望在心理上不觉得吃亏的前提下,获得尽可能多的充实值。
输入
第一行包含两个整数n和X。
接下来n行包含每个课程的信息,原价a_i, 现价b_i,能获得的充实值为w_i ,均为整数。
输出
输出一个数字,表示你能获得的最大充实值
样例
输入
4 100 100 73 60 100 89 35 30 21 30 10 8 10
输出
100
输入
3 100 100 100 60 80 80 35 21 21 30
输出
60
输入
2 100 100 30 35 140 140 100
输出
135
提示
样例1解释
购买1、3、4三门课程,获得总优惠38元,总金额102元超预算2元,满足条件,获得100充实值。
数据规模
对于30\%的数据,n<=15
对于另外30\%的数据,n<=100
对于100\%的数据,n<=500,0<=X<=10000,0<=b_ i<=a_i<=500,1<=w_i<=10^7
D. 树的家园
[HAOI2015]树上染色 gym102222 G. Factories CCF 201909-5 城市规划 (难度递减顺序) 的弱化版
描述
春天来啦,小松鼠们纷纷跑了出来。
它们(一共2\times n只松鼠)聚集到了一颗有2\times n个节点的树上,有2\times n - 1条边,每一条边连接了u_i,v_i,边权为w_i。每个节点都有一颗它们心爱的松果,所以它们刚刚好一人一个位置。
大树觉得,松鼠不能随便排位置,不然会有损自己的形象,于是给松鼠们下了一个难题:
假定第i只松鼠在p_i位置,并且第i只松鼠和第i+n只松鼠是好基友(i\le n)。
我们定义dist(u,v)表示节点u和节点v的简单路径上边的边权之和。
那么,你需要计算出\sum_{i=1}^{n}dist(p_i,p_{i+n}) 的最大值和最小值。
大树答应它们,只要它们能顺利解决这道题,就把松果全送给它们当食物。
松鼠们为难了,你能帮帮它们吗?
输入
第一行,输入一个数n。
接下来2\times n - 1行,每一行输入三个数u_i,v_i,w_i,表示有一条连接u_i和v_i,边权为w_i的双向边。
输出
输出两个数,分别表示最大值和最小值,用一个空格隔开。
样例
输入
2 1 2 1 1 3 2 1 4 3
输出
6 6
提示
数据规模
对于5 \%的数据,1\le n\le 5;
对于10\%的数据,1\le n\le 10;
对于30 \%的数据,1\le n\le 100;
对于50 \%的数据,1\le n\le 1000;
对于70\%的数据,1\le n\le 10^5。
对于100\%的数据,1\le n\le 5\times 10^5。
数据保证这2\times n - 1条边能构成一颗树,并且边权w_i\le 2\times 10^7。
C
#include<stdio.h> #define max(a,b) ((a)>(b)?(a):(b)) const int N=505,M=3e5+5; int n,m,X,v[N],w[N];long long ans,f[M]; int main(){ //freopen("input.txt","r",stdin); scanf("%d%d",&n,&X); for(int i=1,x,y,z;i<=n;i++){ scanf("%d%d%d",&x,&y,&z); if(2*y<=x) X+=x-2*y,ans+=z; else{ ++m; v[m]=2*y-x;w[m]=z; } } for(int i=1;i<=m;i++){ for(int j=X;j>=v[i];j--){ f[j]=max(f[j],f[j-v[i]]+w[i]); } } ans+=f[X]; printf("%lld\n",ans); return 0; }
D
#include<vector> #include<stdio.h> using namespace std; #define mp make_pair #define fi first #define se second #define pb emplace_back typedef pair<int,int> pir; typedef unsigned long long ull; const int N=1e6+5; template<typename T> inline void read(T &x){ register bool f=0;register char ch=getchar();x=0; for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=1; for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0'; if(f) x=-x; } template<typename T,typename...Args> void read(T &x,Args&...args){read(x);read(args...);} int n,m,siz[N];ull ans1,ans2; vector<pir>g[N]; void dfs(int x,int fa){ siz[x]=1; for(auto &t:g[x]){ int &y=t.fi; int &z=t.se; if(y!=fa){ dfs(y,x); siz[x]+=siz[y]; ans1+=1ULL*min(siz[y],n-siz[y])*z; if(siz[y]&1) ans2+=z; } } } int main(){ read(n);n<<=1; for(int i=1,x,y,z;i<n;i++) read(x,y,z),g[x].pb(mp(y,z)),g[y].pb(mp(x,z)); dfs(1,1); printf("%llu %llu\n",ans1,ans2); return 0; }