zoukankan      html  css  js  c++  java
  • CodeForces 916D Jamie and To-do List

    题意

    你需要维护一个任务列表,有 (q) 次操作,每次操作形如以下四种:

    • set a x:设置任务 (a) 的优先级为 (x),如果任务列表中没有 (a) 则加进来。

    • remove a:将任务 (a) 移除列表。

    • query a:求出有多少个任务的优先级比 (a) 的小,如果 (a) 不在列表里输出 (-1)

    • undo d:撤销这次操作之前的 (d) 个操作。

    注意撤销操作可以撤销之前的撤销操作

    ( exttt{Data Range:}1leq qleq 10^5,1leq xleq 10^9,1leqvert avertleq 15)

    题解

    我又是一个不看数据范围的屑 >_<

    为什么这场的 D 比 E 还难写啊

    好久没写可持久化数据结构了,来写个题解复习一下。

    一看到什么撤销操作估计跟可持久化数据结构分不开了。

    看到 query 操作其实可以开一棵可持久化权值线段树来维护一下,然后 set 的话需要一个可持久化数组来维护每个任务的优先级。

    然后按照题意模拟就得了,因为这题的 (xleq 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;
            }
        }
    }
    
  • 相关阅读:
    ANDROID – 單色漸層效果的改良 – GRADIENT SCRIMS(转)
    ANDROID – TOOLBAR 上的 NAVIGATION DRAWER(转)
    ANDROID – TOOLBAR STEP BY STEP(转)
    Android设计和开发系列第二篇:Action Bar(Develop—Training)
    Android设计和开发系列第二篇:Action Bar(Develop—API Guides)
    Android设计和开发系列第二篇:Action Bar(Design)
    Android英文文档翻译系列(6)——LocalBroadcastManager
    Android设计和开发系列第一篇:Notifications通知(Develop—API Guides)
    Android设计和开发系列第一篇:Notifications通知(Develop—Training)
    Apache与Nginx虚拟主机设置(多域名和多端口的区别)
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13586246.html
Copyright © 2011-2022 走看看