A-链接:https://www.nowcoder.com/acm/contest/133/A
来源:牛客网
题目描述
现在有一棵被Samsara-Karma染了k种颜色的树,每种颜色有着不同的价值
Applese觉得Samsara-Karma染的太难看了,于是打算把整棵树重新染成同一种颜色
但是,由于一些奥妙重重的原因,每一次染色Applese可以选择两个有边相连的点,将其中一个染成另一个的颜色。而进行一次这样的操作需要付出两种颜色价值和的代价
现在,Applese的钱要用来买书(game),所以他想要最小化代价
输入描述:
输入包括若干行i
第一行包括一个数n,表示这棵树有n个节点
第二行包括n个数,第i个数表示第i个节点的颜色col
**注意:一个颜色的标号即价值
接下来的n - 1行,每行包括两个数u, v,表示u节点与v节点之间有一条无向边
n ≤ 100000, 1 ≤ coli ≤ 1e9,数据保证是一棵树
输出描述:
输出包括一行
第一行包括一个数,表示最小代价
示例1
输出
复制12
边的输入根本就是多余的,直接枚举所有颜色统计最小的值即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define inf 0x3f3f3f3f3f3f3f 5 int col[100010]; 6 map<int,int>M; 7 int main(){ 8 int n,m,i,j,k; 9 while(cin>>n){ll u,v,tot=0,all=0; 10 M.clear(); 11 for(i=1;i<=n;++i) { 12 scanf("%d",col+i); 13 all+=col[i]; 14 M[col[i]]++; 15 } 16 for(i=1;i<n;++i){ 17 scanf("%d%d",&u,&v); 18 } 19 ll ans=inf; 20 for(i=1;i<=n;++i){ 21 ll tt=M[col[i]]; 22 ans=min(ans,((ll)n-tt)*col[i]+all-tt*col[i]); 23 } 24 cout<<ans<<endl; 25 } 26 return 0; 27 }
B-链接:https://www.nowcoder.com/acm/contest/133/B
来源:牛客网
题目描述
Applese有1个容量为v的背包,有n个物品,每一个物品有一个价值ai,以及一个大小bi
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
输入描述:
第一行三个数v, n, m,分别代表背包容量,物品数量以及需要取出的物品数量
接下来n行,每行两个数ai,bi,分别代表物品价值以及大小
n ≤ 1e5, 1 ≤ m ≤ n, ai ≤ 1e9, v ≤ 1e9, bi ≤ v
输出描述:
仅一行,代表最大的中位数
非常操蛋,因为我把m打成了n,把first打成了second导致debug了一天,浪费很久的时间= =
做法并不难想,将物品分成前,中,后三个部分且每一部分的长度都知道,然后预处理下前/后最小的体积值,
枚举中间的1/2个点,对于奇数长度,直接枚举中点。偶数长度,枚举第一个点,二分查找右边一个的点(之所以能二分是因为first递增
而且rs[]也是递增的),在满足总的体积不超v的情况下使得价值尽可能的大,也就等价于尽可能的找右边的点。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define pii pair<LL,LL> 5 6 pii x[100110]; 7 LL ls[100110],rs[100110]; 8 priority_queue<LL>q; 9 priority_queue<LL>q2; 10 11 void init(int n,int m){ 12 13 int ll=(m-1)/2,rr=(m-1)/2; 14 LL sum=0; 15 for(int i=1;i<=ll;++i){ 16 q.push(x[i].second); 17 sum+=x[i].second; 18 } 19 ls[ll]=sum; 20 for(int i=1+ll;i<=n;++i){ 21 if(q.empty()) continue; 22 if(/*!q.empty()&&*/q.top()>x[i].second){ 23 sum=sum-q.top()+x[i].second; 24 q.pop(); 25 q.push(x[i].second); 26 } 27 ls[i]=sum; 28 } 29 30 sum=0; 31 for(int i=n;i>n-rr;--i){ 32 q2.push(x[i].second); 33 sum+=x[i].second; 34 } 35 rs[n-rr+1]=sum; 36 for(int i=n-rr;i>=1;--i){ 37 if(!q2.empty()&&q2.top()>x[i].second){ 38 sum=sum-q2.top()+x[i].second; 39 q2.pop(); 40 q2.push(x[i].second); 41 } 42 rs[i]=sum; 43 } 44 } 45 int main(){ 46 int n,m,i,j,k; 47 LL v; 48 cin>>v>>n>>m; 49 for(i=1;i<=n;++i) scanf("%lld%lld",&x[i].first,&x[i].second); 50 sort(x+1,x+1+n); 51 init(n,m); 52 int ll=(m-1)/2,rr=(m-1)/2; 53 if(m%2){ 54 LL ans=0; 55 for(i=n-rr;i>ll;--i){ 56 if(ls[i-1]+rs[i+1]+x[i].second<=v) 57 {ans=x[i].first;break;} 58 } 59 cout<<ans<<endl; 60 } 61 else{ 62 LL ans=0; 63 for(i=ll+1;i<n-rr;++i){ 64 int L=i+1,R=n; 65 LL tmp=v-ls[i-1]-x[i].second; 66 while(L<R){ 67 int mid=R-((R-L)>>1); 68 if(n-(mid+1)+1>=rr&&x[mid].second+rs[mid+1]<=tmp) L=mid; 69 else R=mid-1; 70 } 71 if(tmp-x[L].second-rs[L+1]>=0&&n-(L+1)+1>=rr) 72 ans=max(ans,x[i].first+x[L].first); 73 } 74 cout<<ans/2<<endl; 75 } 76 77 return 0; 78 }