D. Segment Intersections 模拟

D. Segment Intersections

题目大意:

image-20200730095152013

遇到了我最讨厌的模拟题。

题解:

难度其实不是很大,但是B题花的时间太多了,这个又没有想的特别明白。

很容易的想到,这个可以分成两种,一个是区间相交,一个是区间不相交。

  • 对于区间相交,这个很简单,首先求出n个相交的和

  • 然后对于每一个求出除开相交还可以1换1的长度

  • 然后求一下能不能1换1解决,不能则要2换1

  • 对于区间不相交,这个稍稍复杂,可以有两种写法

  • 第一种 \(O(1)\):首先贪心的考虑先弥合区间,然后1换1,这样肯定是更优的

  • 然后对于最后一个,可能弥合区间再1换1,不如直接2换1,所以要特判一下。

  • 但是只针对最后一个,假设弥合的代价是 \(x\) ,那么我需要换的是 \(d\) ,那么可以分两种情况:

    • \(d<len\) (\(len\) 表示区间1换1的长度),那么只要 \(2*d>d+x\) 即可
    • \(d>len\) 那么就直接弥合即可
  • 第二种是暴力,直接枚举弥合的数量,其他就直接2换1。

#include <bits/stdc++.h>
#define debug(x) printf("debug:%s=%lld\n",#x,x);
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll n,k;
        scanf("%lld%lld",&n,&k);
        ll l,r,x,y;
        scanf("%lld%lld%lld%lld",&l,&r,&x,&y);
        ll L = max(l,x),R = min(r,y),num = max(0ll,R-L);
        ll len = max(r,y)-min(l,x)-num,cost = max(0ll,L-R);
        k-=num*n;
        ll ans = 0;
        if(k>0){
            //这个一定要有,这个主要是为了有一对已经是弥合的状态,不然后面就不能用 2换1
            ans+=cost;
            ans+=min(len,k);
            k-=min(len,k);
        }
        if(k>0&&len){
            //如果len==0,那么就直接2换1即可
            ll cur = min(n-2,k/len);
//         printf("ss\n");
            k -= cur*len;
            ans += cur*(cost+len);
            if(k>=cost){
                ans+=min(k,len)+cost;
                k-=min(k,len);
            }
        }
//        printf("len=%lld cost =%lld k=%lld ans = %lld\n",len,cost,k,ans);
        if(k>0) ans+=2*k;
        printf("%lld\n",ans);
    }
    return 0;
}
/*
1
1 9
2 9
2 9

*/

猜你喜欢

转载自www.cnblogs.com/EchoZQN/p/13402569.html