zoukankan      html  css  js  c++  java
  • 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 ≤ 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 }
     
    
    
  • 相关阅读:
    java简单计算器,只能鼠标点击数字
    可以掉落和滑动的星星
    servlet生成数字验证码
    web服务器底层-http请求与相应
    Codeforces 990D Graph And Its Complement 【构造】【性质】
    2018美团CodeM编程大赛 Round A Problem 2 下棋 【贪心】
    Codeforces 988F Rain and Umbrellas 【dp】
    Codeforces 988D Points and Powers of Two 【性质】【卡常】
    Codeforces 981D Bookshelves 【dp】【性质】
    POJ 2104 K-th Number 【主席树】【不带修改】
  • 原文地址:https://www.cnblogs.com/zzqc/p/9347500.html
Copyright © 2011-2022 走看看