Loading

CF702 F 题解

拿到这个题首先我按照以前做题的模板,把每个人看做询问。题目给了两个关键字,我无论通过那个关键字当做第一关键字发现都没有一个好的方法。于是果断直接看题解。

这个题的难点在于第一步:是否能想到用数据结构去维护钱。

我们用一个平衡树去维护钱,剩下的就很好想了,有之前排序的基础,我们很容易想到按照质量排序,质量相等的按照价格来排序。然后对于每一个物品,分裂出来后直接在平衡树上打标记。唯一有问题的一点是,我们做的是减法标记,所以如果直接合并会出问题,我们把整棵树分成三部分,\(x,y,z\),当前的钱为 \(c\),令 \(x<c\)\(c\le x<2*c\)\(2*c\le z\)\(y,z\) 两部分都要进行减法。我们对 \(z\) 进行打标记,对 \(y\) 进行每个减去后直接插入的 \(x\) 中,我们考虑一下这样做的复杂度是多少。

上面的那个式子表明,对于我们插入的每一个值,当其被暴力插入的时候,一定会至少减去其一般,也就是说,所有的值被暴力插入的次数是 \(\sum_{i=1}^{^n}\log_2 q_i\),所以我们总的时间复杂度应该为这个式子:

\[ O((n+q+\sum\limits_{i=1}^nlog_2 q_i)\log_2n) \]

上面那个式子大约是 \(1e8\) 这个东西在 4s 的限制下是可以跑过去的。

代码:


#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 200010
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

inline int random(int n){
    return 1ll*rand()*rand()%n+1;
}

typedef pair<int,int> P;

struct Node{
    int val,ls,rs,cnt,id,key;
    P tag;
    inline void Print(){
        printf("val=%d ls=%d rs=%d cnt=%d id=%d tag=%d\n",val,ls,rs,cnt,id,tag.first);
    }
    inline Node(){}
    inline Node(int val,int ls,int rs,int cnt,int id,int key) : val(val),ls(ls),rs(rs),cnt(cnt),id(id),key(key) {}
}p[N];

int root,tot,ans[N];

#define ls(k) p[k].ls
#define rs(k) p[k].rs
struct FHQ_Treap{
    inline int NewNode(int val,int id){
        ++tot;p[tot]=Node(val,0,0,0,id,random(INF));return tot;
    }
    inline void A(int k,P x){
        if(!k) return;
        p[k].val-=x.first;p[k].tag.first+=x.first;
        p[k].tag.second+=x.second;p[k].cnt+=x.second;
    }
    inline void PushDown(int k){
        if(p[k].tag.first){
            A(ls(k),p[k].tag);A(rs(k),p[k].tag);p[k].tag=make_pair(0,0);
        }
    }
    inline void Split(int k,int val,int &x,int &y){
        if(!k){x=y=0;return;}PushDown(k);
        // printf("split k=%d\n",k);p[k].Print();
        if(p[k].val<=val){x=k;Split(rs(k),val,rs(x),y);}
        else{y=k;Split(ls(k),val,x,ls(y));}
    }
    inline int Merge(int x,int y){
        PushDown(x);PushDown(y);if(!x||!y) return x+y;
        if(p[x].key<=p[y].key){ls(y)=Merge(x,ls(y));return y;}
        else{rs(x)=Merge(rs(x),y);return x;}
    }
    inline void Insert(int val,int id){
        int x,y;Split(root,val,x,y);root=Merge(Merge(x,NewNode(val,id)),y);
    }
    inline void Add(int &k,int q){
        int x,y;Split(k,p[q].val,x,y);k=Merge(Merge(x,q),y);
    }
    inline void dfs(int k,int c,int &rt){
        if(!k) return;PushDown(k);dfs(ls(k),c,rt);dfs(rs(k),c,rt);
        p[k].val-=c;p[k].cnt++;p[k].ls=p[k].rs=0;Add(rt,k);
    }
    inline void Opera(int c){
        // printf("c=%d\n",c);
        int x,y,z;Split(root,c-1,x,y);Split(y,2*c-1,y,z);A(z,make_pair(c,1));
        // printf("x=%d y=%d z=%d\n",x,y,z);
        // p[x].Print();p[y].Print();p[z].Print();
        dfs(y,c,x);
        // printf("now x is %d\n",x); p[x].Print();
        root=Merge(x,z);
    }
    inline void dfs2(int k){
        if(!k) return;PushDown(k);ans[p[k].id]=p[k].cnt;
        dfs2(ls(k));dfs2(rs(k));
    }
}tr;

struct node{
    int c,q;
    inline node(){}
    inline node(int c,int q) : c(c),q(q) {}
    inline bool operator < (const node &b) const{
        if(q!=b.q) return q>b.q;
        return c<b.c;
    }
}a[N];

int n,m;

int main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    read(n);for(int i=1;i<=n;i++){read(a[i].c);read(a[i].q);}read(m);
    for(int i=1;i<=m;i++){
        int x;read(x);tr.Insert(x,i);
    }
    // printf("root=%d\n",root);p[root].Print();
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        tr.Opera(a[i].c);
        // tr.dfs2(root);
        // for(int j=1;j<=m;j++) printf("%d ",ans[j]);puts("");
        // p[1].Print();p[2].Print();
        // printf("_______________\n");
    }
    tr.dfs2(root);
    for(int i=1;i<=m;i++) printf("%d ",ans[i]);
    return 0;
}

posted @ 2022-01-24 18:14  hyl天梦  阅读(48)  评论(0编辑  收藏  举报