Educational codes 58 (rated for Div. 2) C. division and union

Keywords: iOS

Topic connection: https://codeforces.com/problemset/problem/1101/C

Abstract: for n line segments, find a dividing point, and divide the line segments into two sets. The line segments of different sets will not have intersections

My own approach is to discretize the endpoints and enumerate them to determine whether they are split points
How to quickly determine whether it is a split point? Use an array sr to record the right end point, an array sl to record the left end point. For the current length I, find the position of i i n sr and sl by dichotomy, which is equivalent to finding the right end point of how many line segments r < = I, and the left end point of how many line segments l > I. then judge whether it is n. note that the set requires non empty, so the complexity seems to be relatively high

#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<stdlib.h>
#include<algorithm>
#include<time.h>
#include<unordered_map>
#define bug1(g) cout<<"test: "<<g<<endl
#define bug2(g,i) cout<<"test: "<<g<<" "<<i<<endl
#define bug3(g,i,k) cout<<"test: "<<g<<" "<<i<<" "<<k<<endl
#define bug4(a,g,i,k) cout<<"test: "<<a<<" "<<g<<" "<<i<<" "<<k<<endl
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int t;
int n;
int l[maxn],r[maxn];
set<int> a;
vector<int>sl,sr;
int main()
{
    ios::sync_with_stdio(0);
    cin>>t;
    while(t--)
    {
        cin>>n;
        a.clear();
        sl.clear();
        sr.clear();
        for(int i =0;i<n;i++)
            {
                cin>>l[i]>>r[i];
                a.insert(l[i]);
                a.insert(r[i]);
                sl.push_back(l[i]);
                sr.push_back(r[i]);
            }
            sort(sl.begin(),sl.end());
            sort(sr.begin(),sr.end());
        int ans=-1;
        for(auto i=a.begin();i!=a.end();i++)
        {
            int r=upper_bound(sr.begin(),sr.end(),*i)-sr.begin(); // You must use the upper bound to give an example
            int l=sl.end()-upper_bound(sl.begin(),sl.end(),*i);
            if(r>0&&l>0&&r+l==n)
            {
                ans=*i;
                break;
            }
        }
        if(ans==-1) cout<<-1<<endl;
        else
        {
            for(int i =0;i<n;i++)
            {
                if(r[i]<=ans) cout<<1;
                else cout<<2;
                if(i==n-1) cout<<endl;
                else cout<<" ";
            }
        }

    }
    return 0;
}

There's a simpler way to watch giant blogs https://blog.csdn.net/CaprYang/article/details/86419347 After sorting, you can directly record the largest r that has appeared before and compare it with the current l. you want to be more complicated ()

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 2e5 + 10;

struct node
{
	int l, r, i;
	bool operator < (const node &oth) const
	{
		return l < oth.l;
	}
}a[MAXN];
bool cmp(const node &a, const node &b)
{
	return a.i < b.i;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	while (T--)
	{
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++)
			scanf("%d%d", &a[i].l, &a[i].r), a[i].i = i;
		sort(a + 1, a + n + 1); //Sort by l
		int k = 0, r = a[1].r; //The farthest r
		for (int i = 2; i <= n; i++)
		{
			if (a[i].l > r) //The current position does not cover the previous r
				k = a[i].l; //Record feasible l
			r = max(r, a[i].r);
		}
		sort(a + 1, a + n + 1, cmp);
		if (k)
			for (int i = 1; i <= n; i++) //Records greater than or equal to k are divided into the second group
				cout << (a[i].l >= k ? 2 : 1) << " ";
		else
			cout << -1;
		cout << endl;
	}

	return 0;
}

Posted by kkeim on Mon, 04 Nov 2019 08:47:47 -0800