【cf1285E】E. Delete a Segment(vector+二分)

传送门

题意:
给出\(n\)个区间,最终区间会合并为多个块。
现在要删除一个区间,问最终剩下的块最多是多少个。

思路:

  • 将区间按左端点排序后,考虑维护区间的前后缀,然后枚举要删除的区间;
  • 处理起来较麻烦,且维护的信息很多;
  • 所以直接维护前缀信息,然后倒着来枚举删除区间,同时动态维护后缀;
  • 统计答案时需要在后缀区间中二分,时间复杂度为\(O(nlogn)\)。

细节见代码:

/*
 * Author:  heyuhhh
 * Created Time:  2020/1/27 10:21:46
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e5 + 5;

int n;
pii p[N];
int pref[N], lst[N];

void run(){
    cin >> n;
    for(int i = 1; i <= n; i++) {
        cin >> p[i].fi >> p[i].se;
    }
    sort(p + 1, p + n + 1);
    pref[1] = 1, lst[1] = p[1].se;
    for(int i = 2; i <= n; i++) {
        if(p[i].fi <= lst[i - 1]) {
            pref[i] = pref[i - 1];
            lst[i] = max(lst[i - 1], p[i].se);
        } else {
            pref[i] = pref[i - 1] + 1;
            lst[i] = p[i].se;
        }
    }
    vector <pii> v;
    int ans = 0;
    for(int i = n; i >= 1; i--) {
        int l = 0, r = sz(v), mid;
        while(l < r) {
            mid = (l + r) >> 1;
            if(v[mid].fi <= lst[i - 1]) r = mid;
            else l = mid + 1;
        }
        ans = max(ans, pref[i - 1] + l);
        while(!v.empty() && v.back().fi <= p[i].se) {
            p[i].se = max(p[i].se, v.back().se);
            v.pop_back();
        }
        v.push_back(p[i]);
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    lst[0] = -INF;
    int T; cin >> T;
    while(T--) run();
    return 0;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/12241552.html

时间: 2024-10-12 05:31:53

【cf1285E】E. Delete a Segment(vector+二分)的相关文章

uva 1463 - Largest Empty Circle on a Segment(二分+三分+几何)

题目链接:uva 1463 - Largest Empty Circle on a Segment 二分半径,对于每个半径,用三分求出线段到线段的最短距离,根据最短距离可以确定当前R下每条线段在[0,L]上的可行区间,存在一个点被可行区间覆盖n次. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using n

Median(vector+二分)

Median Time Limit: 5 Seconds Memory Limit: 65536 KB The median of m numbers is after sorting them in order, the middle one number of them if m is even or the average number of the middle 2 numbers if m is odd. You have an empty number list at first.

codeforces 1285E. Delete a Segment

链接:https://codeforces.com/problemset/problem/1285/E 题意:给一个数轴上有n个线段集,线段集若有相交,则合并为一个新的合并线段集,比如[1,6]和[2,9],因为两个线段有相交,所以要合并为[1,9],先问删掉给定的n个线段集中的任意一个,剩下的n-1个线段组成的新的合并线段集数量最大是多少? 思路: 这道题首先想到的是并查集做法,枚举删除任意一条线段后,剩下的线段组成的集合是多少,取max,这个复杂度有n2 × 并查集复杂度,显然是不行的.那么

E. Delete a Segment(删除一个区间,让并区间最多)

题:https://codeforces.com/contest/1285/problem/E 题意:给定n个区间,最多删除一个区间,让最后的并区间个数最大 #include<bits/stdc++.h> using namespace std; const int M=4e5+5; pair<int,int>a[M]; int countt[M]; int main(){ int t; scanf("%d",&t); while(t--){ int n

HDOJ 5372 Segment Game 树状数组+离散化

因为这题的线段长度是递增的....所以: 题解:对于新插入的线段,查询有多少个线段左端点大于等于该线段的左端点. 再查询有多少个线段的右端点大于该线段右端点, 两者之差就是答案.用两个树状数组搞定.时间复杂度nlog Segment Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 975    Accepted Submiss

hdu5372 Segment Game

Problem Description Lillian is a clever girl so that she has lots of fans and often receives gifts from her fans. One day Lillian gets some segments from her fans Lawson with lengths of 1,2,3... and she intends to display them by adding them to a num

当前插入的线段能完整覆盖存在的几条线段 树状数组 HDU 5372 Segment Game

http://acm.hdu.edu.cn/showproblem.php? pid=5372 Segment Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1284    Accepted Submission(s): 375 Problem Description Lillian is a clever girl so

HDU 5372 Segment Game 树状数组

链接 Segment Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 273    Accepted Submission(s): 48 Problem Description Lillian is a clever girl so that she has lots of fans and often receives gi

Segment Game (hdu 5372 树状数组+离散化)

Segment Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 534    Accepted Submission(s): 132 Problem Description Lillian is a clever girl so that she has lots of fans and often receives gift