CodeForces 916D Jamie and To-do List
2024-10-09 16:18:34
题意
你需要维护一个任务列表,有 \(q\) 次操作,每次操作形如以下四种:
set a x
:设置任务 \(a\) 的优先级为 \(x\),如果任务列表中没有 \(a\) 则加进来。remove a
:将任务 \(a\) 移除列表。query a
:求出有多少个任务的优先级比 \(a\) 的小,如果 \(a\) 不在列表里输出 \(-1\)。undo d
:撤销这次操作之前的 \(d\) 个操作。
注意撤销操作可以撤销之前的撤销操作。
\(\texttt{Data Range:}1\leq q\leq 10^5,1\leq x\leq 10^9,1\leq\vert a\vert\leq 15\)
题解
我又是一个不看数据范围的屑 >_<
为什么这场的 D 比 E 还难写啊
好久没写可持久化数据结构了,来写个题解复习一下。
一看到什么撤销操作估计跟可持久化数据结构分不开了。
看到 query
操作其实可以开一棵可持久化权值线段树来维护一下,然后 set
的话需要一个可持久化数组来维护每个任务的优先级。
然后按照题意模拟就得了,因为这题的 \(x\leq 10^9\) 所以不写结构体式线段树可以免去建树的空间开销。
注意一下空间问题即可通过,这里可能要根据数据范围估算一下空间开销。
代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=2e5+51;
map<string,ll>mp;
ll n,totn,totid,x,id,p,limit=1e9;
string op,str;
ll rt[MAXN<<2],rt2[MAXN<<2],sm[MAXN<<6],ls[MAXN<<6],rs[MAXN<<6];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll getId(string s)
{
return mp.find(s)==mp.end()?mp[s]=++totid:mp[s];
}
inline void update(ll node)
{
sm[node]=sm[ls[node]]+sm[rs[node]];
}
inline ll add(ll l,ll r,ll pos,ll val,ll node)
{
ll cur=++totn;
ls[cur]=ls[node],rs[cur]=rs[node];
if(l==r)
{
return sm[cur]=sm[node]+val,cur;
}
ll mid=(l+r)>>1;
if(pos<=mid)
{
ls[cur]=add(l,mid,pos,val,ls[node]);
}
else
{
rs[cur]=add(mid+1,r,pos,val,rs[node]);
}
return update(cur),cur;
}
inline ll query(ll l,ll r,ll ql,ll qr,ll node)
{
if(ql<=l&&qr>=r)
{
return sm[node];
}
ll mid=(l+r)>>1,res=0;
res+=ql<=mid?query(l,mid,ql,qr,ls[node]):0;
res+=qr>mid?query(mid+1,r,ql,qr,rs[node]):0;
return res;
}
int main()
{
n=read();
for(register int i=1;i<=n;i++)
{
cin>>op,rt[i]=rt[i-1],rt2[i]=rt2[i-1];
if(op=="set")
{
cin>>str,x=read(),id=getId(str),p=query(1,limit,id,id,rt2[i]);
p?rt[i]=add(1,limit,p,-1,rt[i]):1;
rt[i]=add(1,limit,x,1,rt[i]),rt2[i]=add(1,limit,id,x-p,rt2[i]);
}
if(op=="remove")
{
cin>>str,id=getId(str),p=query(1,limit,id,id,rt2[i]);
p?rt[i]=add(1,limit,p,-1,rt[i]):1,rt2[i]=add(1,limit,id,-p,rt2[i]);
}
if(op=="undo")
{
x=read(),rt[i]=rt[i-x-1],rt2[i]=rt2[i-x-1];
}
if(op=="query")
{
cin>>str,id=getId(str),p=query(1,limit,id,id,rt2[i]);
cout<<(p==0||p==1?p-1:query(1,limit,1,p-1,rt[i]))<<endl;
}
}
}
最新文章
- POJ-1068题
- Codeforces 676C Vasya and String(尺取法)
- Caffe 源碼閱讀(一) Blob.hpp
- js获取页面传过来的参数
- NC V6 安装目录各文件夹作用描述
- sql的临时表使用小结
- codevs 1519 过路费 最小生成树+倍增
- Ppthon基础学习之Dict
- poj 2992
- Pods was rejected as an implicit dependency for &;#39;libPods.a&;#39; because its architectures &;#39;x86_64&;#39; didn
- 《玩转Bootstrap(基础)》笔记
- 用css3的cursor:zoom-in/zoom-out实现微博看图片放大镜效果
- BootKit病毒——“异鬼Ⅱ”的前世今生
- Windows10家庭版运行应用提示”管理员已阻止你运行此应用...“的解决办法
- Linux驱动之触摸屏程序编写
- iOS 关于重定向的那些事(NSURLProcotol-WKWebView)
- RabbitMQ入门-发布订阅模式
- java易错题----静态方法的调用
- 关于MVC RouteExistingFiles疑问
- 整理this笔记