专栏文章

题解:P6544 [CEOI2014] Cake

P6544题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mir3kyr4
此快照首次捕获于
2025/12/04 15:11
3 个月前
此快照最后确认于
2025/12/04 15:11
3 个月前
查看原文
如果没有修改操作,那么应该怎么样求?假设 bbaa 左侧,记 mxmx[b,a1][b,a-1] 中的最大美味值,在 [a+1,n][a+1,n] 中找到最靠左的满足 dp>mxd_p>mx 的位置 pp,则我们要先吃完 [b+1,p1][b+1,p-1] 中的蛋糕才会吃 bb,答案易求。我们对 dd 数组维护一个线段树(以下标为位置,权值为 did_i),在树上求区间最大值,以及树上二分查找即可。
问题是我们如何在修改操作中维护这棵线段树。我们记录数组 cc 表示当前权值从大到小排名第 ii 为的蛋糕的下标为 cic_i
假设我们现在要将第 idid 个蛋糕拿到第 ee 位,我们可以考虑把前 e1e-1 位的蛋糕的 dd+1+1,然后把 idid 插入 cec_e(原先的 cec_e 及以后的向后挪动一位)。将 didd_{id} 赋值为原先的 dce+1d_{c_e}+1
这个过程我们模拟即可,因为我们只需要维护长度最长为 1010cc 数组即可。记得在修改 dd 值时在线段树上同步进行修改。
C
/*  Erica N  */
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define int long long
#define ull unsigned long long
#define pii pair<int, int>
#define ps second
#define pf first
#define itn int
#define rd read()
int read(){
    int xx = 0, ff = 1;char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-')ff = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9')xx = xx * 10 + (ch - '0'), ch = getchar();
    return xx * ff;
}
// void write(int out) {
// 	if (out < 0)
// 		putchar('-'), out = -out;
// 	if (out > 9)
// 		write(out / 10);
// 	putchar(out % 10 + '0');
// }
#define cdbg(x...) do { cerr << #x << " -> "; err(x); } while (0)
void err() { cerr << endl; }
template<template<typename...> class T, typename t, typename... A>
void err(T<t> a, A... x) { for (auto v: a) cerr << v << ' '; err(x...); }
template<typename T, typename... A>
void err(T a, A... x) { cerr << a << ' '; err(x...); }


const int N = 3e5 + 5;
const int INF = 1e18;
const int M = 1e7;
const int MOD = 1e9 + 7;

int d[N];
int n;

namespace SGT{
    //区间查询max 树上二分 单点覆盖

    int t[N<<2];

    inline void pushup(int x){
        t[x]=max(t[x<<1],t[x<<1|1]);
    }

    void build(int x,itn l,int r){
        if(l==r){
            t[x]=d[l];
            return ;
        }
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }

    void change(int x,int l,int r,int p,int v){
        if(l==r){
            t[x]=v;
            return ;
        }
        int mid=l+r>>1;
        if(p<=mid)change(x<<1,l,mid,p,v);
        else change(x<<1|1,mid+1,r,p,v);
        pushup(x);
    }

    int query(int x,int l,int r,int pl,int pr){
        if(pl<=l&&pr>=r){
            return t[x];
        }
        int mid=l+r>>1;
        int res=0;
        if(pl<=mid)res=max(res,query(x<<1,l,mid,pl,pr));
        if(pr>mid)res=max(res,query(x<<1|1,mid+1,r,pl,pr));
        return res;
    }

    int locateL(int x,int l,int r,int pl,int pr,int v){
        if(l==r){
            if(t[x]>v)return l;
            return n+1;
        }
        int mid=l+r>>1;
        int res=n+1;
        if(t[x<<1]>v&&mid>=pl)res=locateL(x<<1,l,mid,pl,pr,v);
        if(t[x<<1|1]>v)res=min(res,locateL(x<<1|1,mid+1,r,pl,pr,v));
        return res;
    }

    int locateR(int x,int l,int r,int pl,int pr,int v){
        if(l==r){
            if(t[x]>v)return l;
            return 0;
        }
        int mid=l+r>>1;
        int res=0;
        if(t[x<<1|1]>v&&mid+1<=pr)res=locateR(x<<1|1,mid+1,r,pl,pr,v);
        if(t[x<<1]>v)res=max(res,locateR(x<<1,l,mid,pl,pr,v));
        return res;
    }
}using namespace SGT;

int c[12];
pii b[N];

signed main() {
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    

     n=rd;
     int A=rd;
    for(int i=1;i<=n;i++){
        d[i]=rd;
        b[i]={d[i],i};
    }

    sort(b+1,b+n+1);
    for(int i=1;i<=min(10ll,n);i++){
        c[i]=b[n-i+1].ps;
    }

    build(1,1,n);
    int q=rd;
    while(q--){
        char op;
        cin>>op;
        if(op=='E'){
            int id=rd,e=rd;
            int r=min(n,10ll);
            int cur=INF;
            for(int i=1;i<=r;i++){
                if(id==c[i]){
                    cur=i;
                    break;
                }
            }
            
            for(int i=min(cur-1,r);i>=e;i--){
                c[i+1]=c[i];
            }
            
            for(int i=1;i<e;i++){
                d[c[i]]++;
                change(1,1,n,c[i],d[c[i]]);
            }
            d[id]=d[c[e]]+1;
            change(1,1,n,id,d[id]);
            c[e]=id;
        }else{
            int B=rd;
            if(A==B){
                cout<<0<<'\n';
            }else if(A<B){
                int mx=query(1,1,n,A+1,B);
                int loc=locateR(1,1,n,1,A-1,mx);// >mx
                cout<<B-loc-1<<'\n';

            }else{
                int mx=query(1,1,n,B,A-1);
                int loc=locateL(1,1,n,A+1,n,mx);
                cout<<loc-B-1<<'\n';

            }
        }
    }

}

评论

0 条评论,欢迎与作者交流。

正在加载评论...