1. 程式人生 > >Wannafly挑戰賽20-A,B

Wannafly挑戰賽20-A,B

scribe 成了 name 復制 question names air clear com

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 ≤ coli ≤ 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個物品,每一個物品有一個價值ai,以及一個大小bi
然後他對此提出了自己的疑問,如果我不要裝的物品裝的價值最大,只是一定需要裝m個物品,要使得求出來的物品價值的中位數最大
Applese覺得這個題依然太菜,於是他把這個問題丟給了你
當物品數量為偶數時,中位數即中間兩個物品的價值的平均值

輸入描述:

第一行三個數v, n, m,分別代表背包容量,物品數量以及需要取出的物品數量
接下來n行,每行兩個數ai,bi,分別代表物品價值以及大小 n ≤ 1e5, 1 ≤ m ≤ n, ai ≤ 1e9, v ≤ 1e9, bi ≤ 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 }

 





Wannafly挑戰賽20-A,B