#6085. 「美团 CodeM 资格赛」优惠券

题目描述

用last[x]表示对x进行的上一次操作的位置,vis[x]表示x是否在大楼内。

Splay维护‘?‘的位置。

若x要进楼:

1.若x已在楼内,则去找last[x]到i之间是否有‘?‘,若有,则可以把这个‘?‘当做是上一个x出楼,反之则 出现错误。

2.若x不在楼内,标记x在楼内。

若x要出楼:

1.若x在楼内,标记x不在楼内。

2.若x不在楼内,相同的去找last[x]到i之间是否有‘?‘。

#include<complex>
#include<cstdio>
using namespace std;
const int N=5e5+7;
int n,sz,rot,ans=-1;
int key[N],fat[N],son[N][2],siz[N],last[N];
bool vis[N];
int qread()
{
    int x=0;
    char ch=getchar();
    while(ch<‘0‘ || ch>‘9‘)
    {
        if(ch==‘I‘)return 1;
        if(ch==‘O‘)return 2;
        if(ch==‘?‘)return 3;
        ch=getchar();
    }
    while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x;
}
void Update(int rt)
{
    siz[rt]=siz[son[rt][0]]+siz[son[rt][1]]+1;
}
void Rotate(int x,int &rt)
{
    int a=fat[x],b=fat[a],l=son[a][1]==x,r=l^1;
    if(a==rt)rt=x;
    else son[b][son[b][1]==a]=x;
    fat[son[x][r]]=a;fat[a]=x;fat[x]=b;
    son[a][l]=son[x][r];son[x][r]=a;
    Update(a);Update(x);
}
inline void Splay(int x,int &rt)
{
    while(x!=rt)
    {
        int a=fat[x],b=fat[a];
        if(a!=rt)
            if((son[a][0]==x)^(son[b][0]==a))
                Rotate(x,rt);
            else Rotate(a,rt);
        Rotate(x,rt);
    }
}
void Insert(int v,int k)
{
    int fa=0;
    while(k && key[k]!=v)
        fa=k,k=son[k][key[k]<v];
    k=++sz;
    key[k]=v;siz[k]=1;fat[k]=fa;
    if(fa)son[fa][key[fa]<v]=k;
    Splay(k,rot);
}
void Find(int x,int k)
{
    while(son[k][key[k]<x] && x!=key[k])
        k=son[k][key[k]<x];
    Splay(k,rot);
}
void Delete(int x)
{
    Find(x,rot);
    if(son[rot][0] && son[rot][1])
    {
        int tmp=rot,k=son[rot][1];
        rot=k;
        while(son[k][0])k=son[k][0];
        siz[k]+=siz[son[tmp][0]];
        fat[son[tmp][0]]=k;son[k][0]=son[tmp][0];
        Splay(k,rot);
    }
    else rot=son[rot][0]+son[rot][1];
    fat[rot]=0;
}
int GetNxt(int x)
{
    Find(x,rot);
    if(key[rot]>x)return rot;
    int k=son[rot][1];
    while(son[k][0])k=son[k][0];
    return k;
}
int main()
{
    scanf("%d",&n);
    int tmp,p,x;
    for(int i=1;i<=n;i++)
    {
        p=qread();
        if(p==1)
        {
            x=qread();
            if(vis[x])
            {
                tmp=key[GetNxt(last[x])];
                if(!tmp)
                {
                    ans=i;
                    break;
                }
                else Delete(tmp);
            }
            vis[x]=1;
            last[x]=i;
        }
        if(p==2)
        {
            x=qread();
            if(!vis[x])
            {
                tmp=key[GetNxt(last[x])];
                if(!tmp)
                {
                    ans=i;
                    break;
                }
                else Delete(tmp);
            }
            vis[x]=0;
            last[x]=i;
        }
        if(p==3)Insert(i,rot);
    }
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/LeTri/p/8665739.html

时间: 2024-10-06 09:19:23

#6085. 「美团 CodeM 资格赛」优惠券的相关文章

「题解」「美团 CodeM 资格赛」跳格子

目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞定,最后无奈 \(90pts\) . 然而 \(T2\) 想到很多很奇怪的做法,结果正解在 \(28min\) 之内做出... 结果 \(T3\) 是本人最不擅长的伪期望,直接跳过,啥都没得. 来水一发 \(T1\) 的题解... 题目描述 点这里 考场思路 其实并没有什么十分特别的思路,就是一通乱

「美团 CodeM 资格赛」试题泛做

LibreOJ真是吼啊! 数码 推个式子,把枚举因数转为枚举倍数.然后就发现它是根号分段的.然后每一段算一下就好了. 1 #include <cstdio> 2 #include <cstring> 3 4 #define R register 5 typedef long long ll; 6 struct Data { 7 ll num[10]; 8 inline void clear() 9 { 10 memset(num, 0, 10 << 3); 11 } 1

LibreOJ #6191. 「美团 CodeM 复赛」配对游戏

二次联通门 : LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 /* LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 概率dp 不是很懂为什么这样做... */ #include <cstdio> #include <iostream> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void read (int &now) { for (now = 0; !isdi

LiberOJ #6210. 「美团 CodeM 决赛」tree 树形DP

题目链接:点这里 题解: 需要证明,所求的路径一定是全部权值都为1或者,路径上权值至多有一个为2其余为1且权值2在路径中央. 然后树形DP 设定dp[i][0/1] 以1为根的情况下,以i 节点下子树走分别全1和 走一次2和剩余全走1 的最长链 每遍历一次子树,统计一次答案 下面给出代码 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000&qu

「美团 CodeM 复赛」城市网络

https://loj.ac/problem/6192 内存限制:64 MiB   时间限制:500 ms标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接的连通图),首都为 111 号城市,每个城市售卖价值为 aia_ia?i?? 的珠宝. 你是一个珠宝商,现在安排有 qqq 次行程,每次行程为从 uuu 号城市前往 vvv 号城市(走最短路径),保证 vvv 在 uuu 前往首都的最短路径上. 在每次行程开始时,你手上有价值为 ccc 的珠宝(

「美团 CodeM 初赛 Round B」景区路线规划 概率DP

题意 游乐园被描述成一张 n 个点,m 条边的无向图(无重边,无自环).每个点代表一个娱乐项目,第 i 个娱乐项目需要耗费 ci 分钟的时间,会让小 y 和妹子的开心度分别增加 h1i ,h2i ,他们俩初始的开心度都是 0 .每条边代表一条路,第 i 条边连接编号为 xi , yi 的两个娱乐项目,从 xi 走到 yi 或者从 yi 走到 xi 耗费的时间都是 ti 分钟.小 y 和妹子预计在游乐园里玩 k 分钟.最开始的时候,小 y 和妹子会等概率的随机选择一个娱乐项目开始玩,每玩完一个项目

Loj #6164. 「美团 CodeM 初赛 Round A」数列互质

link : https://loj.ac/problem/6164 莫队傻题,直接容斥做. #include<bits/stdc++.h> #define maxn 100005 #define pb push_back using namespace std; vector<int> g[maxn]; struct ask{ int l,r,K,num,bl; bool operator <(const ask &u)const{ return bl==u.bl?

「美团 CodeM 初赛 Round B」送外卖2---------------状压dp

题目描述 一张 n 个点 m 条有向边的图上,有 q  个配送需求,需求的描述形式为 (si,ti,li,ri)( s_i , t_i , l_i , r_i )(si?,ti?,li?,ri?),即需要从点 si 送到 ti, 在时刻 li 之后(包括 lil_ili? )可以在 sis_isi? 领取货物,需要在时刻 ri 之前(包括 ri)送达 ti ,每个任务只需完成一次. 图上的每一条边均有边权,权值代表通过这条边消耗的时间.在时刻 000 有一个工作人员在点 1 上,求他最多能完成多

#6177. 「美团 CodeM 初赛 Round B」送外卖2(floyed + 三进制枚举 )

 题目大意: 一张  个点  条有向边的图上,有  个配送需求,需求的描述形式为 ,即需要从点  送到 , 在时刻  之后(包括  )可以在  领取货物,需要在时刻  之前(包括 )送达  ,每个任务只需完成一次. 图上的每一条边均有边权,权值代表通过这条边消耗的时间.在时刻  有一个工作人员在点  上,求他最多能完成多少个配送任务. 在整个过程中,可以认为领货跟交货都是不消耗时间的,时间只花费在路程上.当然在一个点逗留也是允许的. 具体思路: 首先对全图跑一个floyed,求一下各点之间的最短