• HPU personal training


    K - Two Contests

    原题链接:https://agc040.contest.atcoder.jp/tasks/agc040_b?lang=en

    题目大意:

    给一个区间集合,将这些区间分为两个集合,求两个区间中线段交集的最大值。

    解题思路:

    首先找到这些区间的右端点在最左端的区间p,左端点在最右端的区间q。

    1. 如果p,q在同一个集合中,那么这个集合的最大交集就是p_r - q_l,而另一个只放一个最大的区间,得到ans1。
    2. 如果不在同一个区间,想一下集合区间的特征,含有p的集合S中,区间的右端点都大于p的右端点,那么他们的最大交集就是p_R - min_L{ L属于集合S} + 1,含有q的集合T中,区间的左端点都小于q的左端点,那么他们的最大交集就是min_R{R属于集合T} - q_l + 1.可以知道如果直接从所有集合中找最合适期间,那么找到的这个区间可能既在S集合中又在T集合中,所以不能这样找。因此要用到后缀最小值。首先对于每一个区间存储R-mxl+1和mnR-L+1两个数据。然后按其中一个数据对数组排列大小,(要从大的开始,因为大的在一个集合中,所有比他小的都在另一个集合中,然后从大到小找两个集合中的最小交集,这样就可以用后缀最小值了。) 

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e5 + 7;
     4 struct aa{
     5     int first,second;
     6 }P; 
     7 aa arr[N];//记录区间 
     8 int minnore[N]; 
     9 aa S[N];
    10 
    11 bool cmp1(aa a, aa b){
    12     return a.first > b.first;
    13 }
    14 
    15 int main(){
    16     int q, L, R, mxL = 0, mnR = 1e9 + 7, RR, LL;
    17     int flag1 = 0, flag2 = 0, maxlen = 0;
    18     scanf("%d", &q);
    19     for(int i = 0; i < q; i ++ ){
    20         scanf("%d%d", &L, &R);
    21         arr[i].first = L;
    22         arr[i].second = R;
    23         if(L > mxL){
    24             mxL = L;
    25             RR = R;
    26             flag1 = i;
    27         }
    28         if(R < mnR){
    29             mnR = R;
    30             LL = L;
    31             flag2 = i;
    32         } 
    33         maxlen = max(maxlen, R - L + 1);
    34     }
    35     int ans1 = maxlen;
    36     if(mnR >= mxL)    ans1 += mnR - mxL + 1;
    37     if(flag1 == flag2){
    38         cout << ans1 << endl;
    39         return 0;
    40     }
    41     for(int i = 0; i < q; i ++ ){
    42         S[i].first = max(arr[i].second - mxL + 1, 0);
    43         S[i].second = max(mnR - arr[i].first + 1, 0);
    44     }
    45     sort(S, S + q, cmp1);
    46     minnore[q-1] = S[q - 1].second;
    47     for(int i = q - 2; i >= 0; i --){
    48         minnore[i] = min(minnore[i + 1], S[i].second);
    49     }
    50     int ans2 = 0;
    51     for(int i = 0; i < q; i ++ ){
    52         ans2 = max(ans2, S[i].first + minnore[i+1]);
    53     }
    54     cout << max(ans2,ans1) <<endl;
    55     return 0;
    56 } 

     

     

  • 相关阅读:
    【HDOJ】4347 The Closest M Points
    【HDOJ】4341 Gold miner
    【HDOJ】4333 Revolving Digits
    【HDOJ】4336 Card Collector
    【HDOJ】4328 Cut the cake
    【HDOJ】4322 Candy
    【HDOJ】4317 Unfair Nim
    串口接收线程退出与优先级问题
    EVC编程与调试过程出现的问题
    Windows CE创建桌面快捷方式
  • 原文地址:https://www.cnblogs.com/meanttobe/p/11892674.html
Copyright © 2020-2023  润新知