Wannafly挑戰賽20-A,B
阿新 • • 發佈:2018-07-21
scribe 成了 name 復制 question names air clear com
i
然後他對此提出了自己的疑問,如果我不要裝的物品裝的價值最大,只是一定需要裝m個物品,要使得求出來的物品價值的中位數最大
Applese覺得這個題依然太菜,於是他把這個問題丟給了你
當物品數量為偶數時,中位數即中間兩個物品的價值的平均值
A-鏈接:https://www.nowcoder.com/acm/contest/133/A
來源:牛客網
題目描述
現在有一棵被Samsara-Karma染了k種顏色的樹,每種顏色有著不同的價值 Applese覺得Samsara-Karma染的太難看了,於是打算把整棵樹重新染成同一種顏色 但是,由於一些奧妙重重的原因,每一次染色Applese可以選擇兩個有邊相連的點,將其中一個染成另一個的顏色。而進行一次這樣的操作需要付出兩種顏色價值和的代價 現在,Applese的錢要用來買書(game),所以他想要最小化代價輸入描述:
輸入包括若幹行
第一行包括一個數n,表示這棵樹有n個節點
第二行包括n個數,第i個數表示第i個節點的顏色col
接下來的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 5int 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