RMQ+二分 - CF 689D Friends and Subsequences

题目:

Friends and Subsequences

题意:

给A,B两个序列,求 maxri=l(Ai)=minri=l(Bi) 的区间数量

思路:

在所有的区间中求极大/小值,第一反应就应该是二分。
当l为定值,随着x的增大, maxxl=iArri 是一个单调不减函数,同理, minxl=iArri 是一个单调不增函数,这里不给出证明,有兴趣自己想一下为什么。
有了上面的规律,很容易想到算法:用RMQ做预处理,然后枚举区间左值,二分区间右值,找到两个函数的相交部分即可,因为不是严格递增递减函数,所以相交部分有可能是一段而不仅仅是一个点,所以做两次二分,一次找到相交部分的左端点,一次找到右端点

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int dmin[maxn][32], dmax[maxn][32];

void RMQ_init(int A[], int B[], int len){
    for (int i = 0; i<len; ++i){
        dmin[i][0] = A[i];
        dmax[i][0] = B[i];
    }
    for (int j = 1; (1 << j) <= len; ++j)
    for (int i = 0; i + (1 << j) - 1<len; ++i){
        dmin[i][j] = min(dmin[i][j - 1], dmin[i + (1 << (j - 1))][j - 1]);
        dmax[i][j] = max(dmax[i][j - 1], dmax[i + (1 << (j - 1))][j - 1]);
    }
    return;
}


int RMQ_min(int L, int R){
    int k = 0;
    while (1 << (k + 1) <= R - L + 1) k++;
    return min(dmin[L][k], dmin[R - (1 << k) + 1][k]);
}

int RMQ_max(int L, int R){
    int k = 0;
    while (1 << (k + 1) <= R - L + 1) k++;
    return max(dmax[L][k], dmax[R - (1 << k) + 1][k]);
}

int arr1[maxn], arr2[maxn];

int main(){
    int n;
    scanf("%d",&n);
    for (int i=0;i<n;++i)
        scanf("%d",arr1+i);
    for (int i=0;i<n;++i)
        scanf("%d",arr2+i);
    RMQ_init(arr2, arr1, n);
    long long sum = 0;
    for (int i=0;i<n;++i){
        int l = i, r = n-1, res1 = -1, res2 = -1;
        if (RMQ_min(l,r)>RMQ_max(l,r)) continue;
        while (l<=r){
            int mid = (l+r) >> 1;
            int minimum = RMQ_min(i,mid), maximum = RMQ_max(i,mid);
            if (minimum == maximum)
                res1 = res1 == -1 ? mid : max(res1, mid);
            if (minimum < maximum)
                r = mid - 1;
            else
                l = mid + 1;
        }
        if (res1 == -1) continue;
        l = i, r = res1, res2 = -1;
        while (l<=r){
            int mid = (l+r) >> 1;
            int minimum = RMQ_min(i,mid), maximum = RMQ_max(i,mid);
            if (minimum == maximum)
                res2 = res2 == -1 ? mid : min(res2, mid);
            if (minimum <= maximum)
                r = mid - 1;
            else
                l = mid + 1;
        }
        sum += res1 - res2 + 1;
    }
    cout<<sum<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个使用Java语言编写的应用程序的命令行运行指令。该程序是一个消息队列中间件的Broker,使用了RocketMQ框架实现。其中的参数含义如下: -server:使用JVM的server模式。在多核CPU上提高性能。 -Xms2g:JVM启动时堆内存的最小值为2G。 -Xmx2g:JVM堆内存的最大值为2G。 -XX:+UseG1GC:使用G1垃圾回收器。 -XX:G1HeapRegionSize=16m:G1垃圾回收器内存区域的大小为16M。 -XX:G1ReservePercent=25:预留25%的空间以避免太满引发的性能问题。 -XX:InitiatingHeapOccupancyPercent=30:G1在堆内存使用达到30%时会触发垃圾回收。 -XX:SoftRefLRUPolicyMSPerMB=0:清除软引用的时间间隔为0,即软引用的对象一旦没有被使用就会被立即清除。 -verbose:gc:打印GC日志。 -Xloggc:/dev/shm/rmq_srv_gc_%p_%t.log:将GC日志输出到/dev/shm/rmq_srv_gc_%p_%t.log文件中。 -XX:+PrintGCDetails:打印GC详细信息。 -XX:+PrintGCDateStamps:打印GC时间戳。 -XX:+PrintGCApplicationStoppedTime:打印应用程序停止时间。 -XX:+PrintAdaptiveSizePolicy:打印自适应策略的信息。 -XX:+UseGCLogFileRotation:启用GC日志文件轮换。 -XX:NumberOfGCLogFiles=5:GC日志文件轮换时保留的文件数目。 -XX:GCLogFileSize=30m:GC日志文件的大小为30M。 -XX:-OmitStackTraceInFastThrow:关闭快速抛出异常时的栈信息。 -XX:+AlwaysPreTouch:在JVM启动时预先分配堆内存。 -XX:MaxDirectMemorySize=15g:最大直接内存大小为15G。 -XX:-UseLargePages:不使用大页面。 -XX:-UseBiasedLocking:不使用偏向锁。 -Drocketmq.client.logUseSlf4j=true:使用SLF4J作为日志框架。 -c ../conf/broker.conf:指定Broker的配置文件路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值