专栏文章
题解:P6544 [CEOI2014] Cake
P6544题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mir3kyr4
- 此快照首次捕获于
- 2025/12/04 15:11 3 个月前
- 此快照最后确认于
- 2025/12/04 15:11 3 个月前
如果没有修改操作,那么应该怎么样求?假设 在 左侧,记 为 中的最大美味值,在 中找到最靠左的满足 的位置 ,则我们要先吃完 中的蛋糕才会吃 ,答案易求。我们对 数组维护一个线段树(以下标为位置,权值为 ),在树上求区间最大值,以及树上二分查找即可。
问题是我们如何在修改操作中维护这棵线段树。我们记录数组 表示当前权值从大到小排名第 为的蛋糕的下标为 。
假设我们现在要将第 个蛋糕拿到第 位,我们可以考虑把前 位的蛋糕的 都 ,然后把 插入 (原先的 及以后的向后挪动一位)。将 赋值为原先的 。
这个过程我们模拟即可,因为我们只需要维护长度最长为 的 数组即可。记得在修改 值时在线段树上同步进行修改。
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 条评论,欢迎与作者交流。
正在加载评论...