2020-2021 ICPC, NERC部分题解

本文提供ICPC和NERC竞赛中三道算法题目的解题思路。A题关注序列中非递减子序列的构建,通过线段树维护状态;H题讨论序列操作,奇数个数选择与中位数消去策略;M题解决数组间的元素匹配,利用平方根分治策略降低复杂度。
摘要由CSDN通过智能技术生成

A:给出一个序列,问能否找出一些点,使得相邻两个数的最小值组成的序列非递减。
首先考虑最长非递减子序列,每个数之间最多能够插入一个比两侧大的数,超过两个就不合法,可以手推或者脑补一下。因此在选择状态转移的时候如果有多个最大值,要选取下标最小的一个,思考一下,如果dp值相同,下标更小的数一定更大,因为后面有更大的数那么可以从这个数进行转移。所以用线段树维护两个数,第一个为dp值,第二个为该位置的值,用last数组表示上一次这个数出现的位置,如果这段区间内有比两侧的数都大的数,那么答案可以为+2,否则+1。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=5e5+5;
int a[maxn],last[maxn];
struct Seg{
   
    int t[maxn<<2];
    int m[maxn<<2];
    void build(int p,int l,int r){
   
        if(l==r) {
   
            t[p]=0;
            m[p]=l;
            return;
        }
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
        t[p]=max(t[p<<1],t[p<<1|1]);
        if(t[p<<1|1]>=t[p<<1]) m[p]=m[p<<1|1];
        else m[p]=m[p<<1];
    }
    void update(int p,int l,int r,int in,int v){
   
        if(l==r){
   
            t[p]=max(t[p],v);
            return;
        }
        int mid=(l+r)>>1;
        if(in<=mid) update(p<<1,l,mid,in,v);
        else update(p<<1|1,mid+1,r,in,v);
        t[p]=max(t[p<<1],t[p<<1|1]);
        if(t[p<<1|1]>=t[p<<1]) m[p]=m[p<<1|1];
        else m[p]=m[p<<1];
    }
    pii query(int p,int l,int r,int ql,int qr){
   
        if(qr<ql) return {
   0,0};
        if(ql<=l&&qr>=r) return {
   t[p],m[p]};
        int mid=(l+r)>>1;
        pii res={
   0,0};
        if(ql<&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值