题意

你需要维护一个任务列表,有 \(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;
}
}
}

CodeForces 916D Jamie and To-do List的更多相关文章

  1. CodeForces 916E Jamie and Tree(树链剖分+LCA)

    To your surprise, Jamie is the final boss! Ehehehe. Jamie has given you a tree with n vertices, numb ...

  2. Codeforces 916C - Jamie and Interesting Graph

    916C - Jamie and Interesting Graph 思路:构造. 对于1到n最短路且素数,那么1到n之间连2 对于最小生成树,找一个稍微大点的素数(比1e5大)构造一个和为这个素数的 ...

  3. Codeforces 916E Jamie and Tree (换根讨论)

    题目链接  Jamie and Tree 题意  给定一棵树,现在有下列操作: $1$.把当前的根换成$v$:$2$.找到最小的同时包含$u$和$v$的子树,然后把这棵子树里面的所有点的值加$x$: ...

  4. codeforces 916E Jamie and Tree dfs序列化+线段树+LCA

    E. Jamie and Tree time limit per test 2.5 seconds memory limit per test 256 megabytes input standard ...

  5. CodeForces 916C Jamie and Interesting Graph (构造)

    题意:给定两个数,表示一个图的点数和边数,让你构造出一个图满足 1-  n 的最短路是素数,并且最小生成树也是素数. 析:首先 1 - n 的最短路,非常好解决,直接 1 连 n 就好了,但是素数尽量 ...

  6. CodeForces 916B Jamie and Binary Sequence (changed after round) (贪心)

    题意:给定两个数字n,m,让你把数字 n 拆成一个长度为 m 的序列a1,a2,a3...am,并且∑2^ai = n,如果有多组,要求序列中最大的数最小,然后再相同就要求除了最大数字典序最大. 析: ...

  7. CodeForces 916A Jamie and Alarm Snooze (水题)

    题意:给定一个数字n,和一个时间,问你每次可以把当前时间往回调n分钟,然后调多少次后时间中包含数字7. 析:直接模拟就好,从当前分钟向后调,注意调成负数的情况就好.很简单. 代码如下: #pragma ...

  8. Codeforces 916B - Jamie and Binary Sequence (changed after round)

    思路: 先取出二进制的每一位,判断总个数是不是小于等于k,如果大于k则不能构成. 通过观察可以发现,每一位的一个可以转换成下一位的两个,因为要使最大位尽可能小,所以如果最大位的所有的个数都可以转换成下 ...

  9. Codeforces 916B Jamie and Binary Sequence ( 模拟 && 思维 )

    题意 : 给出一个数 n ,要求你用 k 个二的幂来组成这个数,要求输出这 k 个二的幂的指数,如果有多解情况则优先输出最大指数最小的那一个且要求按字典序输出,不存在则输出 No 分析 :  先来说一 ...

随机推荐

  1. Linux等待队列(Wait Queue)

    1. Linux等待队列概述 Linux内核的等待队列(Wait Queue)是重要的数据结构,与进程调度机制紧密相关联,可以用来同步对系统资源的访问.异步事件通知.跨进程通信等.在Linux中,等待 ...

  2. spring+springmvc+mybatis+shiro

    创建maven框架https://blog.csdn.net/Ajax_mt/article/details/78549119 具体下边 https://blog.csdn.net/w2222288/ ...

  3. android.widget.TextView.setText() on a null object reference

    错误描述 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView. ...

  4. 关于VS编译报错,但是错误信息未提示问题解决方案

    可能代码中引用了别的类库中的函数,然后未编译被引用库导致编译报错,重新编译被引用库然后再编译当前库即可解决问题

  5. mysql-4-functions

    #进阶4:常见函数(单行函数) /* 将一组逻辑语句封装在方法体中,对外暴露方法名 语法: SELECT 函数名() [FROM 表名] 分类: 1.单行函数:concat,length,ifnull ...

  6. SPI应用 用SPI总线读取气压传感器SCP1000的数据

    Using SPI to read a Barometric Pressure Sensor This example shows how to use the SPI (Serial Periphe ...

  7. 从远程库github.com克隆代码时遇到了如下的问题:

    Warning: Permanently added the RSA host key for IP address '13.250.177.223' to the list of known hos ...

  8. Centos下Oracle11gR2安装教程与自动化配置脚本

    系统环境准备 开发组件与依赖库安装 安装centos时选择Server with GUI,右面的可以不勾选,后面统一来装 配置本地yum源 以上包如果缺乏可配置本地yum源进行安装 sudo moun ...

  9. chattr 和 lsattr 命令详解

    lsattr 命令 lsattr 命令用于查看文件的第二扩展文件系统属性. 语法: lsattr(选项)(参数) 选项: -E:可显示设备属性的当前值,但这个当前值是从用户设备数据库中获得的,而不是从 ...

  10. docker-命令帮助

    1. 命令参考     http://www.runoob.com/docker/docker-command-manual.html2. docker-命令,可以使用docker --help查看或 ...