0718题解-FOIWC兔

题意

艾斯洛克是数兔结构大师,他出了一题给你做:

定义数组\(A\)的循环移位操作\(F(A)\):将\(A\)最前面的元素移到末尾,其余元素依次往前移动。例如\(F([1,2,3,4,5])=[2,3,4,5,1]\)

给定一个\(1 \sim N\)的排列\(P\),接下来有\(Q\)随机生成的操作。

每次操作给出\(L\)\(R\)\(K\),将\(P[1,n]\)进行\(K\)次循环移位操作,即将\(P[1,n]\)使用函数\(F\)迭代\(K\)次。

每次操作之后,令\(A\)表示将整个排列\(P[1,n]\)经过若干次循环移位操作后,\(P[1,n]\)的逆序对数最大值,你需要求出\(P[1,n]\)至少经过多少次循环移位操作后,逆序对数能达到\(A\)答案可以是\(0\),即不进行任何循环移位操作。询问对原排列没有任何影响。

思路&题解

考试的时候蠢了,想的是枚举移动的距离i,然后算每次i对前i-1个数和后n-i个数的贡献,于是一道简单题都没做出来。
其实我们换个思考的方式,每次移动以后就真的移动了,把当前这第i个数当做第1个数看,那它的逆序对数肯定是\(n-2*p[i]+1\)
这样我们只要求个前缀和最大值就好!!!
随机生成操作和求前缀和最大值都可以用fhq轻松的维护

#include<bits/stdc++.h>
using namespace std;
#define LL long long 
const int N = 3e5 + 11;
int n, m;
int rt, tot;
struct node{
    int pos; LL sum, ma;
    int ls, rs; 
    int key, val, sz;
}t[N];
int read(){
    int x = 0;
    char ch = getchar();
    while(ch > '9' || ch < '0')ch = getchar();
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - 48, ch = getchar();
    return x;
}
void push_up(int x){
    if(!x)return ;
    int ls = t[x].ls, rs = t[x].rs;
    t[x].sz = t[ls].sz + t[rs].sz + 1;
    t[x].sum = t[ls].sum + t[rs].sum + t[x].val;
    LL lv = t[ls].ma;
    LL pv = t[ls].sum + t[x].val;
    LL rv = t[ls].sum + t[x].val + t[rs].ma;
    if(pv >= rv){
        t[x].pos = t[ls].sz + 1;
        t[x].ma = pv;
    }
    else t[x].pos = t[ls].sz + 1 + t[rs].pos, t[x].ma = rv;
    if(lv >= t[x].ma){
        t[x].pos = t[ls].pos;
        t[x].ma = lv;
    }
}
int merge(int x, int y){
    if(!x || !y)return x + y;
    if(t[x].key <= t[y].key){
        t[x].rs = merge(t[x].rs, y);
        push_up(x);
        return x;
    }
    else{
        t[y].ls = merge(x, t[y].ls);
        push_up(y);
        return y;
    }
}
void split(int rt, int &x, int &y, int k){
    if(!rt){
        x = y = 0;
        return ;
    }
    int ls = t[rt].ls, rs = t[rt].rs;
    if(t[ls].sz + 1 <= k){
        x = rt;
        split(rs, t[rt].rs, y, k - t[ls].sz - 1);
    }
    else{
        y = rt;
        split(ls, x, t[rt].ls, k);
    }
    push_up(x); push_up(y);
}
void insert(int x){
    int p = ++tot;
    t[p].pos = t[p].sz = 1;
    t[p].key = rand();
    t[p].ma = t[p].sum = t[p].val = x;
    rt = merge(rt, p);
}
void print(int u, int res){
    if(!u)return ;
    int ls = t[u].ls, rs = t[u].rs;
    printf("u=%d ls=%d rs=%d val=%d ma=%lld pos=%d sum=%lld i=%d\n", u, ls, rs, t[u].val, t[u].ma, t[u].pos, t[u].sum, t[ls].sz + 1 + res);
    print(ls, res);
    print(rs, res + t[ls].sz + 1);
}
int main(){
    //freopen("rabbit.in", "r", stdin);
    srand(time(0));
    t[0].ma = -1e8;
    cin>>n>>m;
    int x = 0;
    for(int i = 1;i <= n; i++){
        x = read();
        //printf("%d ", n - 2 * x + 1);
        insert(n - 2 * x + 1);
    }
    //puts("");
    //printf("ma=%lld pos=%d\n", t[rt].ma, t[rt].pos);
    //print(rt, 0);
    int l, r, k;
    while(m--){
        l = read(); r = read(); k = read();
        k %= (r - l + 1);
        if(k){
            int x, y, z, p;
            split(rt, x, y, l - 1);
            split(y, y, z, r - l + 1);
            split(y, y, p, k);
            rt = merge(x, merge(merge(p, y), z));
        }
        printf("%d\n", t[rt].ma > 0 ? t[rt].pos : 0);
    }
    return 0;
}

原文链接: https://www.cnblogs.com/dqk2003/p/13338640.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    0718题解-FOIWC兔

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/368555

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午6:29
下一篇 2023年3月2日 下午6:29

相关推荐