• Codeforces 1027F Session in BSU


    题目传送门

      传送门I

      传送门II

      传送门III

    题目大意

      有$n​$门科目有考试,第$i​$门科目有两场考试,时间分别在$a_i, b_i (a_i < b_i)​$,要求每门科目至少参加一场考试,不能在同一个时间参加两场考试,问最后参加的考试最早的时间是什么。

      这几天,我怎么做的都是水题Emm....

      考虑先将$a_i, b_i$离散化。

      对于每一门考试,在$a_i, b_i$间连一条无向边。

      对于每个连通块,讨论:

    • 如果边数大于点数,显然无解
    • 如果边数等于点数,那么答案必须大于等于点权中的最大值。
    • 如果边数小于点数,那么最大不可用的时候会产生若干个基环树,所以答案必须大于等于点权中的次大值。

      并查集随便维护一下就行了。

    Code

      1 /**
      2  * Codeforces
      3  * Problem#1027F
      4  * Accepted
      5  * Time: 873ms
      6  * Memory: 63000k
      7  */
      8 #include <algorithm>
      9 #include <iostream>
     10 #include <cstdlib>
     11 #include <cstdio>
     12 #include <vector>
     13 using namespace std;
     14 typedef bool boolean;
     15 
     16 template <typename T>
     17 void pfill(T* pst, const T* ped, T val) {
     18     for ( ; pst != ped; *(pst++) = val);
     19 }
     20 
     21 typedef class Input {
     22     protected:
     23         const static int limit = 65536;
     24         FILE* file; 
     25 
     26         int ss, st;
     27         char buf[limit];
     28     public:
     29         
     30         Input():file(NULL)    {    };
     31         Input(FILE* file):file(file) {    }
     32 
     33         void open(FILE *file) {
     34             this->file = file;
     35         }
     36 
     37         void open(const char* filename) {
     38             file = fopen(filename, "r");
     39         }
     40 
     41         char pick() {
     42             if (ss == st)
     43                 st = fread(buf, 1, limit, file), ss = 0;//, cerr << "str: " << buf << "ed " << st << endl;
     44             return buf[ss++];
     45         }
     46 }Input;
     47 
     48 #define digit(_x) ((_x) >= '0' && (_x) <= '9')
     49 
     50 Input& operator >> (Input& in, unsigned& u) {
     51     char x;
     52     while (~(x = in.pick()) && !digit(x));
     53     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     54     return in;
     55 }
     56 
     57 Input& operator >> (Input& in, unsigned long long& u) {
     58     char x;
     59     while (~(x = in.pick()) && !digit(x));
     60     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     61     return in;
     62 }
     63 
     64 Input& operator >> (Input& in, int& u) {
     65     char x;
     66     while (~(x = in.pick()) && !digit(x) && x != '-');
     67     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
     68     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     69     u *= aflag;
     70     return in;
     71 }
     72 
     73 Input& operator >> (Input& in, long long& u) {
     74     char x;
     75     while (~(x = in.pick()) && !digit(x) && x != '-');
     76     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
     77     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     78     u *= aflag;
     79     return in;
     80 }
     81 
     82 Input in (stdin);
     83 
     84 #define pii pair<int, int>
     85 
     86 int n, m;
     87 int *uf;
     88 int *es;
     89 int *mx, *smx;
     90 pii* ps;
     91 vector<int> br;
     92 
     93 int find(int x) {
     94     return (uf[x] == x) ? (x) : (uf[x] = find(uf[x]));
     95 }
     96 
     97 inline void init() {
     98     in >> n;
     99     ps = new pii[(n + 1)];
    100     for (int i = 1; i <= n; i++)
    101         in >> ps[i].first >> ps[i].second;
    102 }
    103 
    104 inline void descrete() {
    105     for (int i = 1; i <= n; i++) {
    106         br.push_back(ps[i].first);
    107         br.push_back(ps[i].second);
    108     }
    109     sort(br.begin(), br.end());
    110     m = unique(br.begin(), br.end()) - br.begin();
    111     for (int i = 1; i <= n; i++) {
    112         ps[i].first = lower_bound(br.begin(), br.begin() + m, ps[i].first) - br.begin();
    113         ps[i].second = lower_bound(br.begin(), br.begin() + m, ps[i].second) - br.begin();
    114     }
    115 }
    116 
    117 void addEdge(int u, int v) {
    118     if (find(u) != find(v)) {
    119         u = find(u), v = find(v);
    120         es[u] += es[v];
    121         if (mx[u] < mx[v])
    122             smx[u] = mx[u], mx[u] = mx[v];
    123         else if (smx[u] < mx[v])
    124             smx[u] = mx[v];
    125         smx[u] = ((smx[u] > smx[v]) ? (smx[u]) : (smx[v]));
    126         uf[v] = u;
    127     }
    128     es[find(u)]++;
    129 }
    130 
    131 int res = -1;
    132 inline void solve() {
    133     uf = new int[m];
    134     es = new int[m];
    135     mx = new int[m];
    136     smx = new int[m];
    137 
    138     for (int i = 0; i < m; i++)
    139         uf[i] = i, es[i] = -1, mx[i] = i, smx[i] = -1;
    140     for (int i = 1; i <= n; i++)
    141         addEdge(ps[i].first, ps[i].second);
    142     for (int i = 0; i < m; i++)
    143         if (find(i) == i) {
    144             if (es[i] > 0) {
    145                 res = -1;
    146                 break;
    147             }
    148             if (!es[i])
    149                 res = max(res, mx[i]);
    150             else
    151                 res = max(res, smx[i]);
    152         }
    153     
    154     if (res == -1)
    155         puts("-1");
    156     else
    157         printf("%d
    ", br[res]);
    158 }
    159 
    160 int main() {
    161     init();
    162     descrete();
    163     solve();
    164     return 0;
    165 }
  • 相关阅读:
    装饰器的写法以及应用环境
    面向对象中super的作用
    os与sys模块的作用与常用方法
    python re模块
    python 冒泡排序,二分法
    正则表达式
    python 高阶内置函数
    python 内置函数
    python 生成器和生成器表达式
    python 函数名的应用(第一类对象),闭包,迭代器
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9853501.html
Copyright © 2020-2023  润新知