首页 > 其他分享 >题解:CF916D Jamie and To-do List

题解:CF916D Jamie and To-do List

时间:2024-08-30 20:37:36浏览次数:4  
标签:node rt int 题解 sum Jamie List rc query

题意

维护一个数据结构,支持以下几种操作:

  • set ai xi:设置任务 \(a_i\) 的优先级为 \(x_i\),如果该列表中没有出现则加入该任务。
  • remove a_i:删除该任务。
  • query a_i:求优先级比 \(a_i\) 小的任务个数,如果没有则输出 \(-1\)。
  • undo sum:删除此次操作之前的 \(sum\) 次操作。

分析

前三个操作是非常典型的平衡树操作,考虑使用平衡树或者动态开点线段树。

第四个带撤回,考虑使用可持久化数据结构。

本篇题解使用可持久化动态开点线段树解决。

维护两棵线段树,一棵维护区间和用于记录优先级,一棵维护某任务是否存在。

注意本题强制在线,其他的内容就是板子。

AC 记录

Code

#include<bits/stdc++.h>
using namespace std;

namespace SegT
{
    struct node
    {
        int sum;
        node *lc, *rc;
        node() {memset(this, 0, sizeof *this);}
        void push_up() 
        {
            sum=0;
            if(lc) sum+=lc->sum;
            if(rc) sum+=rc->sum;
        }
    };

    #define lc(x) (x?x->lc:0)
    #define rc(x) (x?x->rc:0)
    #define mid ((l+r)>>1)
    #define lson x->lc, l, mid
    #define rson x->rc, mid+1, r

    void modify(node *pre, node *&x, int l, int r, int p, int v)
    {
        x=pre?new node(*pre):new node;
        if(l==r) return x->sum+=v, void();
        if(p<=mid) modify(lc(pre), lson, p, v);
        if(p>mid)  modify(rc(pre), rson, p, v);
        x->push_up();
    }

    int query(node *x, int l, int r, int L, int R)
    {
        if(!x) return 0;
        if(L<=l&&r<=R) return x->sum;
        int ret=0;
        if(L<=mid) ret+=query(lson, L, R);
        if(R>mid)  ret+=query(rson, L, R);
        return ret;
    }
}

namespace SegT2
{
    struct node
    {
        int v;
        node *lc, *rc;
        node() {memset(this, 0, sizeof *this);}
    };

    void build(node *&x, int l, int r)
    {
        x=new node;
        if(l==r) return;
        build(lson);
        build(rson);
    }

    void modify(node *pre, node *&x, int l, int r, int p, int v)
    {
        x=new node(*pre);
        if(l==r) return x->v=v, void();
        if(p<=mid) modify(pre->lc, lson, p, v);
        if(p>mid)  modify(pre->rc, rson, p, v);
    }

    int query(node *x, int l, int r, int p)
    {
        if(l==r) return x->v;
        if(p<=mid) return query(lson, p);
        if(p>mid)  return query(rson, p);
    }
}

unordered_map<string, int> ids;

SegT::node *rt[100005];
SegT2::node *exist[100005];

int main()
{
    ios::sync_with_stdio(0);
    int q, xi;
    const int n=1e9, m=1e5;
    cin>>q;
    string s, op;
    build(exist[0], 1, m);
    for(int i=1;i<=q;i++)
    {

        rt[i]=rt[i-1];
        exist[i]=exist[i-1];
        cin>>op;
        if(op[0]=='u')
        { 
            cin>>xi;
            rt[i]=rt[i-1-xi];
            exist[i]=exist[i-1-xi];
        }
        else
        {
            cin>>s;
            if(!ids.count(s)) ids[s]=ids.size()+1;
            int a=ids[s];
            if(op[0]=='s') 
            {
                cin>>xi;
                int va=query(exist[i], 1, m, a);
                if(va) modify(rt[i], rt[i], 1, n, va, -1);
                modify(exist[i], exist[i], 1, m, a, xi);
                modify(rt[i], rt[i], 1, n, xi, 1);
            }
            if(op[0]=='q') 
            {
                int ans=0;
                int va=query(exist[i], 1, m, a);
                if(va>1) ans=query(rt[i], 1, n, 1, va-1);
                if(!va) ans=-1;
                cout<<ans<<endl;
            }
            if(op[0]=='r') 
            {
                int va=query(exist[i], 1, m, a);
                if(!va) continue;
                modify(rt[i], rt[i], 1, n, va, -1);
                modify(exist[i], exist[i], 1, m, a, 0);
            }
        }
    }
}

标签:node,rt,int,题解,sum,Jamie,List,rc,query
From: https://www.cnblogs.com/redacted-area/p/18389459

相关文章

  • 题解:CF916B Jamie and Binary Sequence (changed after round)
    题意把一个数分解成恰好\(k\)个\(2^{a_i}\)次方的和,可以重复,要求保证最大的\(a_i\)要尽可能的小时,\(a\)的字典序尽可能大,输出序列\(a\)。分析首先我们借助二进制拆出一个满足\(n=\sum2^{a_i}\)序列\(a\),满足\(a\)的长度最小。若此时\(a\)的长度大于\(k\),显......
  • 题解:CF914C Travelling Salesman and Special Numbers
    题意定义\(\operatorname{popcount}(x)\)为\(x\)二进制下\(1\)的个数。定义对\(x\)的一次操作:\(x\gets\operatorname{popcount}(x)\),显然任意正整数经过若干次操作后会变为\(1\)。给定\(n\)和\(k\),其中\(n\)是在二进制下被给出,求出所有不大于\(n\)且将其变为......
  • 题解:CF915G Coprime Arrays
    题意我们称一个大小为\(n\)的数组\(a\)互质,当且仅当\(\gcd(a_1,a_2,\cdots,a_n)=1\)。给定\(n,k\),对于每个\(i\)\((1\lei\lek)\),你都需要确定这样的数组的个数——长度为\(n\)的互质数组\(a\),满足对每个\(j\)\((1\lej\len)\),都有\(1\lea_j\lei\)。分析......
  • [COCI2012-2013#2] INFORMACIJE 题解
    前言题目链接:洛谷。题意简述你需要构造一个\(1\simn\)的排列\(a\),满足\(m\)个条件,格式如下:1xyv:\(\max\limits_{i=l}^ra_i=v\)。2xyv:\(\min\limits_{i=l}^ra_i=v\)。题目分析首先这个最值很难受,考虑能不能转化成我们喜欢的二元关系......
  • Luogu P10997 Partition 题解 [ 蓝 ] [ 轮廓 dp ]
    Partition:一道dp神题,用到了以轮廓线的轨迹来做dp的技巧,和敲砖块这题的状态设计有点相似。观察首先观察样例,发现整张图可以看作是被两条线分隔开的。同时每个颜色的四个方向上又存在一大堆奇怪的性质,很容易发现这两条线一条是从左上到右下的线,另一条是从右下到左上的线。暴......
  • 【Qt笔记】QListView控件详解
     目录引言一、QListView基本概念1.1定义与功能1.2架构原理二、QListView基本使用2.1创建QListView和Model2.2设置QListView的属性2.3处理用户交互三、QListView高级技巧3.1自定义委托3.2使用QStandardItemModel3.3实现拖放功能四、QListView......
  • CF603E 题解
    题意给定一个\(n\)个结点的无向图,初始没有边。接下来有\(m\)个询问,每次向图中加入一条连接\((u,v)\)权值为\(w\)的边。每次加边后,查询是否存在一个边集\(E\),满足当图中只有\(E\)中的边时,所有点的度数均为奇数。同时你还要最小化\(\max\limits_{(u,v,w)\inE}......
  • python嵌套列表(Nested List)
    题目要求:        给定每个学生的姓名和成绩,将它们存储在嵌套列表中,并打印出成绩第二低的学生的姓名。如果有多个学生成绩第二低,则按字母顺序打印他们的姓名。使用到的函数:set()        将成绩列表转换为集合,集合自动去重,因此相同的成绩只会出现一次。 ......
  • 【Mysql】mysql count主键字段很慢超时 执行计划Select tables optimized away ,最终调
     背景: mysql表 主键字段count,速度很慢,耗时将近30s   从执行计划可以看出:explainSELECTCOUNT(rule_id)ASdataCountFROM`sku_safe_stock_rule`;   原理分析:SelecttablesoptimizedawaySELECT操作已经优化到不能再优化了(MySQL根本没有遍历......
  • CF891E Lust 题解
    题目链接点击打开链接题目解法会不了\(egf\)/ll我们把贡献变成\(\prod\limits_{j\neqi}a_j=\prod\limits_{j=1}^na_j-\prod\limits_{j=1}^n(a_i-[i=j])\)即答案为一开始的乘积\(-\)\(k\)次操作之后所有数乘积的期望因为有顺序,所以用\(egf\)的形式表示最后乘积的期......