• Codeforces Round #610 (Div. 2) A-E简要题解


    contest链接: https://codeforces.com/contest/1282

    A. Temporarily unavailable

    题意: 给一个区间L,R通有网络,有个点x,在x+r和x-r范围内,没有网络,问在这个区间上有网络的长度范围

    思路:枚举区间覆盖情况,注意细节

    AC代码:

     1 #include<iostream>
     2 #include<string>
     3 #include<vector>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 typedef long long ll;
     9 ll mod = 1e9+7;
    10 int main(){
    11     int q;cin>>q;
    12     while(q--){
    13         ll a,b,c,d;
    14         cin>>a>>b>>c>>d;
    15         if(a>b) swap(a,b);
    16         ll l = c-d,r = c+d;
    17         if(b<=l) {cout<<b-a<<endl;continue;}
    18         if(a>=r) {cout<<b-a<<endl;continue;}
    19         if(l<=a&&r>=b) {cout<<0<<endl;continue;    }    
    20         if(l>=a && r<=b){
    21             cout<<b-a-2*d<<endl;
    22             continue;
    23         }
    24         if(l<=a&&r>=a&&r<=b){
    25             cout<<b-r<<endl;
    26             continue;
    27         }
    28         if(l>=a&&l<=b&&r>=b){
    29             cout<<(l-a)<<endl;
    30             continue;
    31         }
    32     }
    33     return 0;
    34 }

    B1.K for the Price of One (Easy Version) 略 直接搞Hard Version

    B2. K for the Price of One (Hard Version)

    题意: 商店买东西,商店有n个物品,每个物品有自己的价格,商店有个优惠活动,当你买恰好k个东西时可以只为其中最贵的那个付款,求有限的钱中买到的最多的物品数量,你可以多次使用优惠。

    思路:把所有商品的价格排序从小到大一遍,设第i个物品的价格是a[i],Sum[i]表示购买前i个物品花费的钱,作为前缀和。可以发现当你买了当第i个物品时,那么只需要支付Sum[i-k] + a [i] 即可,因为你买了当前的物品,可以赠送k-1个,那直接贪心着把小于等于当前这个物品价格的前K-1个物品直接赠送了,只需要支付a[i]费用,再支付一下sum[i-k]即可,维护整个过程sum[i] = sum[i-k] + a[i]即可。

    AC代码:

     1 #include<iostream>
     2 #include<string>
     3 #include<vector>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 typedef long long ll;
     9 ll mod = 1e9+7;
    10 const int maxn = 2e5+10;
    11 int main(){
    12     int q;cin>>q;
    13     while(q--){
    14         ll n,p,k;cin>>n>>p>>k;
    15         ll a[maxn];
    16         a[0] = 0;
    17         for(int i = 1;i<=n;i++) cin>>a[i];
    18         sort(a+1,a+n+1);
    19         ll ans = 0;
    20         // 2 3 4 5 7 
    21         ll sum[n+1];
    22         memset(sum,0,sizeof(sum));
    23         sum[0] = 0;
    24         sum[1] = a[1];
    25         for(int i = 2;i<=k;i++){
    26             sum[i] = sum[i-1] + a[i];//前k个物品价格必须都要算上,此时没有优惠卷
    27         }
    28         for(int i = k;i<=n;i++){
    29             sum[i] = sum[i-k] + a[i];
    30         }
    31         for(int i = 0;i<=n;i++){
    32             if(p>=sum[i]) ans = i ;
    33         }
    34         cout<<ans<<endl;
    35     }
    36     return 0;
    37 }

    C. Petya and Exam

    题意:  有一个人参加考试,考试只有两种题,一种是简单题,每道题耗时固定为a;另一种是困难题,每道题耗时固定为b,保证b>a。解出一道题得分都是1。考试的规则并不只是写多少题得多少分,鼓励提前交卷。假如你没有提前交卷,那么有一部分的题目会列为“必做题”,当“必做题”的题目没有全部被完成的话,这门课就算0分;否则得到与题数相同的分数,包括“必做”和“非必做”的。

    题意: 题意很明显需要按题目的“必做时间”按照升序排列起来,然后贪心着做,从头开始遍历每道题目的必做时间。假如遍历到第i个题了,当前时间为T,那么如果在T-1时刻交卷,首先需要把前面必须做的所有题目做完,假设这个过程花费了Ti时间,然后剩下了T - Ti的时间,那么我们就在剩下的时间内贪心着先做尽可能多剩余的简单题,再做难题,记录此时的ans,不断遍历所有题目的必须做时间到最后,也不断的更新ans的最大值。最终的ans就是答案

    AC代码:

     1 #include<iostream>
     2 #include<string>
     3 #include<vector>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 typedef long long ll;
     9 ll mod = 1e9+7;
    10 const int maxn = 2e5+10;
    11 struct node{
    12     int dif;
    13     int ti;
    14 }g[maxn];
    15 bool cmp(node a,node b){
    16     if(a.ti !=b.ti ) return a.ti<b.ti ;
    17     return a.dif <b.dif ; 
    18 }
    19 int main(){
    20     int q;cin>>q;
    21     while(q--){
    22         ll n,t,a,b;
    23         cin>>n>>t>>a>>b;
    24         ll cnta = 0,cntb = 0;
    25         for(int i = 1;i<=n;i++){
    26             int Td;cin>>Td;
    27             if(Td == 0) cnta++;
    28             else cntb++;
    29             g[i].dif = Td;
    30         }
    31         for(int i = 1;i<=n;i++){
    32             int T;cin>>T;
    33             g[i].ti = T;
    34         }
    35         sort(g+1,g+n+1,cmp);//按必做时间先排序
    36         g[n+1].ti = t+1;
    37         ll ans = 0,c1 = 0,c2 = 0;//c1 c2统计必做题目的个数
    38         for(int i = 1;i<=n+1;i++){
    39             ll cur = a*c1 + b*c2;
    40             ll time = g[i].ti - 1 - cur;//必做题目花费的时间
    41             if(time>=0){//如果有多余的时间,那么尽可能做更多的简单题,再做难题
    42                 ll ta = min(time/a,cnta-c1);
    43                 time-=ta*a;
    44                 ll tb = min(time/b,cntb-c2);
    45                 ans = max(ans,c1+c2+ta+tb);
    46             }
    47             if(g[i].dif == 0) c1++;
    48             else c2++;
    49         }
    50         cout<<ans<<endl;
    51     }
    52     return 0;
    53 }

    D题是交互题,没见过,ACM中没见过,先略了

    E.The Cake Is a Lie

    题意:给的是一张平面图,是一个n边形,每次可以切一刀,切出一个三角形,最终切成n-2个三角形。题目给出所切三角形的三个顶点的编号,以及三角形的编号。问你切出的三角形顺序,以及按顺序输出原始n边形顶点的所有编号,可以逆序输出也顺序输出。

    题解:有点类似拓扑排序。首先输入三角形三个点,a,b,c,统计出V[a] Xor b Xor c,同理统计V[b],V[c],这样可以保证V[i]的值只能是0 Xor 与i相连的两个点,即使三角形有共用边,多次Xor会消除公用边相连的点。根据这个性质,可以顺序输出所有点的编号。

             那么三角形顺序怎么输出呢?首先发现如果一条边是被两个三角形公用的,那么可以依据这条边把两个三角形相连,这样把三角形作为一个节点从而形成了一个图,这个图结构是一颗树,我们就随便找一个叶子节点,从叶子节点开始dfs遍历一遍,输出三角形编号即可。

    AC代码:

     1 #include<iostream>
     2 #include<vector>
     3 #include<cstring>
     4 #include<map>
     5 #include<algorithm>
     6 using namespace std;
     7 const int maxn = 1e+5;
     8 int v[maxn];
     9 vector<int> g[maxn];
    10 int visit[maxn];
    11 void dfs(int x){ //从叶子节点开始搜索,因为叶子节点必定代表着最靠外的三角形,它的度是1
    12     visit[x] = 1;
    13     for(int i = 0;i<g[x].size() ;i++){
    14         int cur = g[x][i];
    15         if(visit[cur] ==0) dfs(g[x][i]);
    16 //        dfs(g[x][i]);
    17     }
    18     cout<<x<<" ";
    19 }
    20 int main(){
    21     int t;cin>>t;
    22     while(t--){
    23         int n;
    24         cin>>n;
    25         for(int i = 0;i<=maxn;i++){
    26             v[i] = 0;//初始化V数组
    27             visit[i] = 0;//初始化访问数组
    28             g[i].clear() ;
    29         }
    30         map<pair<int,int>,vector<int> > mp;
    31         for(int i = 0;i<n-2;i++){
    32             int a,b,c;
    33             cin>>a>>b>>c;
    34             if(a>b) swap(a,b);
    35             if(b>c) swap(b,c);
    36             if(a>b) swap(a,b);
    37             v[a]^=b,v[a]^=c;//Xor操作
    38             v[b]^=a,v[b]^=c;
    39             v[c]^=a,v[c]^=b;
    40             mp[{a,b}].push_back(i+1);//添加一条边a,b,以及所共用的三角形i+1
    41             mp[{a,c}].push_back(i+1);
    42             mp[{b,c}].push_back(i+1);
    43         }
    44         int a,b;
    45         for(auto h:mp){
    46             if(h.second.size()==1){ //随便找一条边,只共用一个三角形
    47                 a = h.first.first;
    48                 b = h.first.second;
    49             //    break;
    50             }
    51         }
    52         cout<<a<<" "<<b;//输出这条边
    53         for(int i = 0;i<n-2;i++){
    54             int t = a^v[b];//开始做Xor操作。具体可以用笔模拟一下这个过程,理解更清楚
    55             cout<<" "<<t;
    56             a = b,b = t;
    57         }
    58         cout<<endl;
    59         for(auto h:mp){
    60             if(h.second.size() == 2){
    61                 int u = h.second[0],v = h.second[1];
    62                 g[u].push_back(v),g[v].push_back(u);//根据共用边以三角形为一个点建图
    63             }
    64         }
    65         dfs(1);
    66         cout<<endl;
    67     }
    68     return 0;
    69 }
     
     
  • 相关阅读:
    SAP库存账龄分析报表
    elasticsearch 同义词配置搜索
    elasticsearch 上下文
    git 修改源路径 修改项目地址
    intellij IDEA 无限试用
    Kubernetes 安装Redis集群
    helm安装ingress
    安装Helm
    Kubernetes Rook + Ceph
    GIT 将工作区恢复到上次提交的内容 commit your changes or stash them before you can merge Your local changes to the following files would be overwritten by merge
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12130146.html
Copyright © 2020-2023  润新知