2023年icpc济南 Rainbow Subrarray

对于a[i+1]=a[i]+1的问题,通常做法都是b[i]=a[i]-i,这样问题就变成了找连续的相等数组。最小的操作数一定是把它变成该数组的中位数。经典问题了。找中位数可以用树状数组实现,在树状数组上二分即可。计算操作数可以分成两个部分计算,假设区间[l, r],中位数的下标为mid,中位数的值为val,以中位数为界,分成前后两部分,前面部分为 (mid - l + 1) * val - sum[l, mid],后面部分为sum[mid+1, r] - (r - mid) * val,其中sum[l, r]表示区间[l, r]的和。

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const long long inf=1e18;
const int N=5e5+10;
ll T;
ll n,m,k;
ll ans,a[N];
multiset <ll> s1,s2;
ll zuo,you,zhong;
bool jiou = 0;

inline ll read() {
    ll sum = 0, ff = 1; char c = getchar();
    while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
    while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
    return sum * ff;
}

void chushihua() {
    s1.clear(); s2.clear();
    s1.insert(-inf); s2.insert(inf);
    zuo = you = zhong = 0;
    jiou = 0;
}

inline void add(ll x) {
    if(!jiou) {
        ll A = *(--s1.end());
        ll B = *s2.begin();
        if(A<=x && x<=B) { zhong = x; }
        else if(A>x) {
            s1.erase(s1.find(A));
            s1.insert(x);
            zuo += x-A;
            zhong = A;
        }
        else if(B<x) {
            s2.erase(s2.find(B));
            s2.insert(x);
            you += x-B;
            zhong = B;
        }
    }
    else {
        if(x>=zhong) {
            s1.insert(zhong); zuo += zhong;
            s2.insert(x); you += x;
        }
        else {
            s2.insert(zhong); you += zhong;
            s1.insert(x); zuo += x;
        }
        zhong = 0;
    }
    jiou ^= 1;
}

inline void del(ll x) {
    ll A = *(--s1.end());
    ll B = *s2.begin();
    if(!jiou) {
        if(A>=x) {
            s1.erase(s1.find(x)); zuo -= x;
            s2.erase(s2.find(B)); you -= B;
            zhong = B;
        }
        else {
            s2.erase(s2.find(x)); you -= x;
            s1.erase(s1.find(A)); zuo -= A;
            zhong = A;
        }
    }
    else {
        if(zhong==x) {}
        else if(x>zhong) {
            s2.erase(s2.find(x));
            s2.insert(zhong);
            you += zhong-x;
        }
        else {
            s1.erase(s1.find(x));
            s1.insert(zhong);
            zuo += zhong-x;
        }
        zhong = 0;
    }
    jiou ^= 1;
}

int main() {
	T = read();
	while(T--) {
        chushihua();
    	n = read(); k = read();
    	for(ll i=1;i<=n;i++) a[i] = read()-i;
        a[n+1] = inf;
    	ll now = 1;
        ans = 1; 
        add(a[1]); jiou = 1;
        for(ll i=1;i<=n;i++) {
            while(you-zuo<=k) { ans = max(ans,now-i+1); add(a[++now]); }
            del(a[i]);
        }
        cout<<ans<<endl;
	}
    return 0;
}

posted @ 2026-02-23 11:45  曾翎一  阅读(3)  评论(0)    收藏  举报