zoukankan      html  css  js  c++  java
  • CF1418D Trash Problem(双平衡树维护)

    题意:

    Vova决定打扫房间。可以将房间表示为坐标轴OX。房间里有n堆垃圾,第i堆的坐标是整数pi。所有桩具有不同的坐标。

    让我们将总清理定义为以下过程。此过程的目标是在不超过两个不同的x坐标下收集所有桩。为了实现此目标,Vova可以执行几次(可能为零)移动。在移动期间,他可以选择一些x,并使用扫帚将所有堆从x移动到x + 1或x-1。请注意,他无法选择要移动多少个桩。

    此外,有两种查询类型:

    0 x-从坐标x移除一堆垃圾。确保此时在坐标x中有一个桩。
    1 x-将一堆垃圾添加到坐标x。可以确保此时在坐标x中没有桩。
    请注意,有时房间中的垃圾堆为零。

    Vova如果想在进行任何查询之前进行彻底清理,则想知道他可以花费的最少移动次数。他还想在应用每个查询后知道此移动次数。查询以给定顺序应用。请注意,总清理实际上并没有发生,也不会改变堆的状态。它仅用于计算移动次数。

    为了更好地理解,请阅读下面的“注释”部分以查看第一个示例的说明。

    输入项
    输入的第一行包含两个整数n和q(1≤n,q≤105)-分别是所有查询之前的房间中的桩数和查询数。

    输入的第二行包含n个不同的整数p1,p2,…,pn(1≤pi≤109),其中pi是第i堆的坐标。

    接下来的q行描述查询。第i个查询用两个整数ti和xi(0≤ti≤1;1≤xi≤109)描述,其中,如果需要从坐标xi中删除桩,则ti为0;如果需要添加,则为1。坐标xi的一堆。保证对于ti = 0,在当前桩组中有这样的桩,对于ti = 1,在当前桩组中没有这样的桩。

    输出量
    打印q + 1个整数:在第一个查询之前和q个查询中的每个查询之后,Vova进行总清理的最小移动次数。

    题解:

    大概意思就是支持插入和删除,每次询问集合里最大数和最小数的差减去最大的相邻数的差。

    开两颗平衡树,分别维护数值本身和差值。比赛时写出了很多bug没改出来。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+100;
    const int inf=2e9;
    int a[maxn];
    struct Treap_tree {
        int ch[2];
        int v;
        int dat;//优先级 
        int size;//子树节点数 
        int cnt;//重复数 
    }t[maxn];
    int tot;
    int root;
    int newNode (int v) {
        tot++;
        t[tot].v=v;
        t[tot].dat=rand();//随机优先级
        t[tot].size=1;
        t[tot].cnt=1;
        t[tot].ch[0]=0;
        t[tot].ch[1]=0;
        return tot; 
    } 
    void pushup (int x) {
        t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
    }
    void build () {
        root=newNode(-inf);
        t[root].ch[1]=newNode(inf);
        pushup(root);
    }
    void rotate (int &id,int d) {
        int tt=t[id].ch[d^1];
        t[id].ch[d^1]=t[tt].ch[d];
        t[tt].ch[d]=id;
        id=tt;
        pushup(t[id].ch[d]);
        pushup(id);
    }
    void ins (int &id,int v) {
        if (!id) {
            id=newNode(v);
            return;
        }
        if (v==t[id].v) t[id].cnt++;
        else {
            ins(t[id].ch[v>t[id].v],v);
            if (t[id].dat<t[t[id].ch[v>t[id].v]].dat) rotate(id,v<t[id].v);
        }
        pushup(id);
    }
    void remove (int &id,int v) {
        if (!id) return;
        if (v==t[id].v) {
            if (t[id].cnt>1) {
                t[id].cnt--;
                pushup(id);
                return;
            }
            if (t[id].ch[0]||t[id].ch[1]) {
                if (!t[id].ch[1]||t[t[id].ch[0]].dat>t[t[id].ch[1]].dat) {
                    rotate(id,1);
                    remove(t[id].ch[1],v);
                }
                else {
                    rotate(id,0);
                    remove(t[id].ch[0],v);
                }
                pushup(id);
            }
            else
                id=0;
            return;
        }
        remove(t[id].ch[v>t[id].v],v);
        pushup(id);
    }
    int rk (int id,int v) {
        if (!id) return 0;
        if (v==t[id].v) 
            return t[t[id].ch[0]].size+1;
        else if (v<t[id].v)
            return rk(t[id].ch[0],v);
        else
            return t[t[id].ch[0]].size+t[id].cnt+rk(t[id].ch[1],v);
    }
    int kth (int id,int k) {
        if (!id) return inf;
        if (k<=t[t[id].ch[0]].size)
            return kth(t[id].ch[0],k);
        else if (k<=t[t[id].ch[0]].size+t[id].cnt)
            return t[id].v;
        else
            return kth(t[id].ch[1],k-t[t[id].ch[0]].size-t[id].cnt);
    }
    int get_pre (int id,int v) {
        int pre;
        while (id) {
            if (t[id].v<v)
                pre=t[id].v,id=t[id].ch[1];
            else
                id=t[id].ch[0];
        }
        return pre;
    }
    int get_next (int id,int v) {
        int nxt;
        while (id) {
            if (t[id].v>v)
                nxt=t[id].v,id=t[id].ch[0];
            else
                id=t[id].ch[1];
        }
        return nxt;
    }
    int get_max (int id) {
        int Max=0;
        while (t[id].ch[1]) {
            if (t[id].v!=inf&&t[id].v!=-inf)
                Max=max(Max,t[id].v);
            id=t[id].ch[1]; 
        }
        if (t[id].v!=inf&&t[id].v!=-inf)
            Max=max(Max,t[id].v);
        return Max;
    }
    int get_min (int id) {
        int Min=inf;
        while (t[id].ch[0]) {
            if (t[id].v!=inf&&t[id].v!=-inf)
                Min=min(Min,t[id].v);
            id=t[id].ch[0]; 
        }
        if (t[id].v!=inf&&t[id].v!=-inf)
            Min=min(Min,t[id].v);
        return Min;
    }
    map<int,int> mp;
    set<int> st,wjm;
    int main () {
        int n,q;
        scanf("%d%d",&n,&q);
        build();
        for (int i=1;i<=n;i++) scanf("%d",a+i),ins(root,a[i]),wjm.insert(a[i]);
        int cnt=n;
        sort(a+1,a+n+1);
        for (int i=1;i<n;i++) {
            mp[a[i+1]-a[i]]++;
            st.insert(a[i+1]-a[i]);
        }
        int ans=a[n]-a[1];
        if (st.size())printf("%d
    ",ans-*st.rbegin());
        else printf("%d
    ",ans);
        while (q--) {
            int op;
            int x;
            int tt=0;
            scanf("%d%d",&op,&x);
            if (op==1) {
                wjm.insert(x);
                cnt++;
                ins(root,x);
                int nxt=get_next(root,x);
                int pre=get_pre(root,x);
                //printf("%d %d
    ",nxt,pre);
                if (nxt!=inf&&pre!=-inf) {
                    mp[nxt-pre]--;
                    if (!mp[nxt-pre]) st.erase(nxt-pre);
                    mp[x-pre]++;
                    if (!st.count(x-pre)) st.insert(x-pre);
                    mp[nxt-x]++;
                    if (!st.count(nxt-x)) st.insert(nxt-x);
                }
                else if (nxt==inf&&pre!=-inf) {
                    mp[x-pre]++;
                    if (!st.count(x-pre)) st.insert(x-pre);
                }
                else if (pre==-inf&&nxt!=inf) {
                    mp[nxt-x]++;
                    if (!st.count(nxt-x)) st.insert(nxt-x);
                }
            }
            else {
                wjm.erase(x);
                cnt--;
                remove(root,x);
                int nxt=get_next(root,x);
                int pre=get_pre(root,x);
                //printf("%d %d
    ",nxt,pre);
                if (nxt!=inf&&pre!=-inf) {
                    mp[nxt-x]--;
                    if (!mp[nxt-x]) st.erase(nxt-x);
                    mp[x-pre]--;
                    if (!mp[x-pre]) st.erase(x-pre);
                    mp[nxt-pre]++; 
                    if (!st.count(nxt-pre)) st.insert(nxt-pre);
                }
                else if (nxt==inf&&pre!=-inf) {
                    mp[x-pre]--;
                    if (!mp[x-pre]) st.erase(x-pre);
                    
                }
                else if (pre==-inf&&nxt!=inf) {
                    mp[nxt-x]--;
                    if (!mp[nxt-x]) st.erase(nxt-x);
                }
            }
            if (cnt<=2||!st.size()) {
                printf("0
    ");
                continue;
            }
            int r=*wjm.rbegin();
            int l=*wjm.begin();
            ans=r-l;
            //printf("%d %d
    ",l,r);
            printf("%d
    ",ans-*st.rbegin());
        } 
    }
  • 相关阅读:
    CentOS6.5 安装 tomcat
    CentOS6.5 安装 jdk1.7
    CentOS6.5 mysql 5.5安装
    java使用split切割字符串的时候,注意转义字符
    hibernate中设置BigDeCimal的精度
    powerdesinger中建立一个表后,出现Existence of index的警告
    MySQL数据库一个字段对应多个值得模糊查询
    系统收到了多个不同的 Content-Disposition 标头。为了避免遭到 HTTP 响应拆分攻击,这种情况是不允许的。
    下载的文件名字当前时间(精确到秒)+ 随机数
    简单的poi导出excel文件
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13673274.html
Copyright © 2011-2022 走看看