• 3744. 【TJOI2014】电影评分(movie)


    Description

    \(\mathrm{Z}\) 发明了一套新的电影评分系统。这套系统有三种操作:发布新电影、电影评分、以及询问电影评分的排名。具体是这样运作的:如果是发布新电影,并且这部电影的所有主演之前均没有出现过,那么这部电影的评分为 0,否则这部电影的评分为最近一部与该电影至少有一个共同主演的电影的分;如果是对电影进行评分,那么这部电影的评分就变成之前评分与新的评分的平均数;如果是查询排名,则根据评分输出相应排名。评分最高的为第一名。如果有多部电影分数相同,那么输出最早的一部。电影的评分在 0 到 5 之间。

    Solution

    有种做法是暴力,利用快排可以在 \(\mathcal O(n)\) 的时间内求出区间第 \(k\) 大,做到总时间复杂度为 \(\mathcal O(n^2)\),吸下氧应该能过。

    正解是后缀平衡树,将小数分成整数部分和小数部分,小数部分用二进制表示,然后来比较。

    但正解我也不会,我就只打了 \(\mathrm{Splay}\),由于怕被卡精度于是用了 \(\mathrm{long\ double}\)

    剩下的就跟普通的 \(\mathrm{Splay}\) 差不多。

    Code

    #include<cstdio>
    #include<algorithm>
    #define N 100005
    #define eps 1e-60
    #define ldb long double
    using namespace std;
    int n,cnt,rt,t[N],lst[N],size[N],f[N],c[N][2];
    ldb val[N];
    char ch[16];
    ldb Abs(ldb x) {return x<0?-x:x;}
    void Update(int x)
    {
        int l=c[x][0],r=c[x][1];
        size[x]=size[l]+size[r]+1;
    }
    void Rotate(int x,int &k)
    {
        int y=f[x],z=f[y],l=x==c[y][1],r=l^1;
        r=l^1;
        if (y==k) k=x;
        else c[z][y==c[z][1]]=x;
        f[c[x][r]]=y;f[y]=x;f[x]=z;
        c[y][l]=c[x][r];c[x][r]=y;
        Update(x);Update(y);
    }
    void Splay(int x,int &k)
    {
        while (x!=k)
        {
            int y=f[x],z=f[y];
            if (y!=k)
            {
                if (x==c[y][1]^y&&c[y][1]^y==c[z][1]) Rotate(x,k);
                else Rotate(y,k);
            }
            Rotate(x,k);
        }
    }
    void Insert(int &now,int x,int fa)
    {
        if (!now)
        {
            now=x;
            f[now]=fa;
            c[now][0]=c[now][1]=0;
            Splay(now,rt);
            return;
        }
        if (val[x]>val[now]||Abs(val[x]-val[now])<eps&&t[x]<t[now]) Insert(c[now][0],x,now);
        else Insert(c[now][1],x,now);
    }
    void Delete(int x)
    {
        Splay(x,rt);
        if (c[x][0]*c[x][1]==0)
        {
            rt=c[x][0]+c[x][1];
            f[c[x][0]+c[x][1]]=0;
            return;
        }
        int pre=c[x][0],suf=c[x][1];
        while (c[pre][1]) pre=c[pre][1];
        while (c[suf][0]) suf=c[suf][0];
        Splay(pre,rt);Splay(suf,c[pre][1]);
        c[suf][0]=f[x]=0;
        Update(pre);Update(suf);
    }
    int Get(int now,int rk)
    {
        if (size[c[now][0]]+1==rk) return now;
        if (rk<=size[c[now][0]]) return Get(c[now][0],rk);
        return Get(c[now][1],rk-size[c[now][0]]-1);
    }
    int main()
    {
        freopen("movie.in","r",stdin);
        freopen("movie.out","w",stdout);
        scanf("%d",&n);
        while (n--)
        {
            scanf("%s",ch);
            if (ch[0]=='R')
            {
                int x,num,act,k=0;
                scanf("%d%d",&x,&num);
                for (int i=1;i<=num;++i)
                {
                    scanf("%d",&act);
                    if (t[lst[act]]>t[k]) k=lst[act];
                    lst[act]=x;
                }
                val[x]=val[k];
                t[x]=++cnt;
                size[x]=1;
                Insert(rt,x,0);
            }
            else if (ch[0]=='C')
            {
                int x;ldb v;
                scanf("%d%Lf",&x,&v);
                Delete(x);
                val[x]=(val[x]+v)/2;
                Insert(rt,x,0);
            }
            else if (ch[0]=='Q')
            {
                int x;
                scanf("%d",&x);
                printf("%d\n",Get(rt,x));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    波形捕捉:(9)写入到WAV文件
    C#基础回顾:GridView全选演示
    VS.net和Reflector 图标解释
    Dot Net屏幕传输 v1.0
    C#基础回顾:用GDI+绘制验证码
    波形捕捉:(8)使用“捕捉缓冲区”
    DirectX编程:C#中利用Socket实现网络语音通信[初级版本]
    DirectX编程:[初级]C#中利用DirectSound播放WAV格式声音[最少只要4句话]
    GroupingView控件 使用经验
    Dot Net下实现屏幕图像差异获取v2.0
  • 原文地址:https://www.cnblogs.com/Livingston/p/15808729.html
Copyright © 2020-2023  润新知