整数对区间交叉判断

奇怪,这个没法加目录嘛?

题源网址

有大约两道题考察了这个知识
Codeforces Round 910 (Div.2)D题
CF Round 905 div3 的D题
这边建议,先看第二道题,再去看第一道题,第二道题是第一道的基础
第一道题

题目

在这里插入图片描述

输入输出范例:

输入:

6
3
1 3 5
3 3 3
2
1 2
1 2
2
1 2
2 1
4
1 2 3 4
5 6 7 8
10
1 8 2 5 3 5 3 1 1 3
2 9 2 4 8 2 3 5 3 1
3
47326 6958 358653
3587 35863 59474

输出:

4
2
2
16
31
419045

范例解释:

Note
In the first test case, each of the possible swaps does not change the array b
.

In the second test case, the absolute beauty of the array b
without performing the swap is |1−1|+|2−2|=0
. After swapping the first and the second element in the array b
, the absolute beauty becomes |1−2|+|2−1|=2
. These are all the possible outcomes, hence the answer is 2
.

In the third test case, it is optimal for Kirill to not perform the swap. Similarly to the previous test case, the answer is 2
.

In the fourth test case, no matter what Kirill does, the absolute beauty of b
remains equal to 16
.>

题意解析

给你两个长度为 n 的数列 a , b ,现在让你可以选择两个下标 i 和 j , 进行一次操作,交换 b i 和 b j 的值,使得 ∑ i = 1 n ∣ a i − b i ∣ 最大化 给你两个长度为n的数列a,b,现在让你可以选择两个下标i 和j,\\进行一次操作,交换b_i和b_j的值,使得\sum_{i=1}^{n}|a_i-b_i|最大化 给你两个长度为n的数列ab,现在让你可以选择两个下标ij,进行一次操作,交换bibj的值,使得i=1naibi最大化

题意深度揭露

这道题本质就是让你找到两对数
a i 和 b i 以及 a j 和 b j 使得把 ( m a x ( a i , b i ) − m i n ( a j − b j ) ) 最大化 另一方面,由于 a i , b i 的可互换性,把每一个 a i 到 b i 的整数区间 抽象成 x 坐标轴上一段线段,那么问题就转换成,判断这 n 个线 段中是否有两个线段是没有交叉的,并且找到距离最远的两个 无交叉线段 , 求出他们之间的距离,比如说( 1 , 2 )代表 1 到 2 的线段,( 7 , 8 )代表 7 到 8 一段线段,它们之间的距离是 7 − 1 = 6 a_i和b_i以及a_j和b_j使得把(max(a_i,b_i)-min(a_j-b_j))最大化\\另一方面,由于a_i,b_i的可互换性,把每一个a_i到b_i的整数区间\\抽象成x坐标轴上一段线段,那么问题就转换成,判断这n个线\\段中是否有两个线段是没有交叉的,并且找到距离最远的两个\\无交叉线段,求出他们之间的距离,比如说(1,2)代表\\1到2的线段,(7,8)代表7到8一段线段,它们之间的距离是\\7-1=6 aibi以及ajbj使得把(max(ai,bi)min(ajbj))最大化另一方面,由于ai,bi的可互换性,把每一个aibi的整数区间抽象成x坐标轴上一段线段,那么问题就转换成,判断这n个线段中是否有两个线段是没有交叉的,并且找到距离最远的两个无交叉线段,求出他们之间的距离,比如说(12)代表12的线段,(78)代表78一段线段,它们之间的距离是71=6

代码呈现

#include "bits/stdc++.h"
using namespace std;
using ll=long long;
const ll  N=1e9+10;
const int M=2e5+10;
inline void solve() {
    int n;cin>>n;vector<pair<int,int> > arr,ans;
    vector<int>a,b,mi,ma;
    for(int i=0;i<n;i++){
        int tmp;cin>>tmp;a.emplace_back(tmp);
    }
    for(int i=0;i<n;i++){
        int tmp;cin>>tmp;b.emplace_back(tmp);
    }
    ll res=0;
    for(int i=0;i<n;i++){
        res+=abs(a[i]-b[i]);
        mi.emplace_back(min(a[i],b[i]));
        ma.emplace_back(max(a[i],b[i]));
    }
    sort(mi.begin(),mi.end());
    sort(ma.begin(),ma.end());
    if(mi[mi.size()-1]<ma[0]){
        cout<<res<<endl;
        return;
    }else {
        res+=2*(mi[mi.size()-1]-ma[0]);
        cout<<res<<endl;
        return;
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int num=1;
    //sieve();
    cin>>num;
    while(num--)
        solve();
    return 0;
}

代码解析

首先把每一个区间(线段)的左端点记录下来成一个数组,右端点记录下来成一个数组,然后取左端点中最大的那个左端点x(代表最右面的那个线段的右端点),以及右端点中最小的那个右端点y(最左面的那个线段的左端点),如果x>y那么说明任意两个区间都有公共区间,证明了你交换任意两个区间,他的所求值都不会变(这个自己想),如果x<y,那么如果交换这个最左侧的区间中的b值和最右侧区间的b值,得到的这道题所求值可以比交换之前多2*(y-x)

第二道题

题目

在这里插入图片描述

输入输出范例

输入:

12

  • 1 2
  • 3 4
  • 2 3
  • 2 2
  • 3 4
  • 3 4
  • 3 4
  • 1 2
  • 3 4
  • 2 2
  • 2 3
  • 3 4

输出:

NO
YES
YES
YES
YES
YES
NO
NO
YES
NO
NO
NO

范例解释:

Note
In the example, after the second, third, fourth, and fifth operations, there exists a pair of segments (1,2)
and (3,4)
that do not intersect.

Then we remove exactly one segment (3,4)
, and by that time we had two segments. Therefore, the answer after this operation also exists.

题意解析

这道题每一次的询问操作就是让你判断是否存在两个无交集的区间

代码呈现

#include "bits/stdc++.h"
using namespace std;
using ll=long long;
const ll  N=1e9+10;
const int M=2e5+10;
inline void solve() {
    int n;cin>>n;
    multiset<int> l,r;
    while(n--){
        char tmp;cin>>tmp;int a,b;cin>>a>>b;
        if(tmp=='+'){
            l.emplace(a);
            r.emplace(b);
        }else {
            l.erase(l.find(a));
            r.erase(r.find(b));
        }
        if(!l.empty())
        if(*l.rbegin()-*r.begin()>0){
            printf("Yes\n");
        }else printf("No\n");
        else printf("No\n");
    }

}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int num=1;
    //sieve();
    //cin>>num;
    while(num--)
        solve();
    return 0;
}

额,不用多说了吧

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值