Wannafly挑战赛20-A,B

A-链接:https://www.nowcoder.com/acm/contest/133/A
来源:牛客网

题目描述

现在有一棵被Samsara-Karma染了k种颜色的树,每种颜色有着不同的价值
Applese觉得Samsara-Karma染的太难看了,于是打算把整棵树重新染成同一种颜色
但是,由于一些奥妙重重的原因,每一次染色Applese可以选择两个有边相连的点,将其中一个染成另一个的颜色。而进行一次这样的操作需要付出两种颜色价值和的代价
现在,Applese的钱要用来买书(game),所以他想要最小化代价

输入描述:

输入包括若干行
第一行包括一个数n,表示这棵树有n个节点
第二行包括n个数,第i个数表示第i个节点的颜色col
i

**注意:一个颜色的标号即价值
接下来的n - 1行,每行包括两个数u, v,表示u节点与v节点之间有一条无向边
n ≤ 100000, 1 ≤ col i ≤ 1e9,数据保证是一棵树

输出描述:

输出包括一行
第一行包括一个数,表示最小代价
示例1

输入

复制
4
2 3 4 3
1 2
2 3
3 4

输出

复制
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个物品,每一个物品有一个价值a i,以及一个大小b i
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值

输入描述:

第一行三个数v, n, m,分别代表背包容量,物品数量以及需要取出的物品数量
接下来n行,每行两个数a i,b i,分别代表物品价值以及大小
n ≤ 1e5, 1 ≤ m ≤ n, a i ≤ 1e9, v ≤ 1e9, b i ≤ v

输出描述:

仅一行,代表最大的中位数
示例1

输入

复制
20 5 3
3 5
5 6
8 7
10 6
15 10

输出

复制
8

非常操蛋,因为我把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 }
 
 
    

猜你喜欢

转载自www.cnblogs.com/zzqc/p/9347500.html