ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

@codeforces - 702F@ T-Shirts

2019-10-17 17:01:19  阅读:211  来源: 互联网

标签:rt node ch return 702F NIL int codeforces Shirts


目录


@description@

有 n 件 T-shirt,第 i 件 T-shirt 有一个 ci 和 qi,分别表示费用与质量。
同时有 k 个顾客,第 j 个顾客准备了 bj 的金钱去购买 T-shirt。

每个顾客的购买策略是相同的:
他会买他的资金范围内 q 值最大的一件,如果有多个选 c 最小的一件,每种 T-shirt 只买1 次。
重复购买,直到所有的 T-shirt 他都买不起或者他都买过了。

求每位顾客最终可以购买的 T-shirt 数量。

Input
第一行一个整数 n (1 ≤ n ≤ 2·10^5),表示 T-shirt 的种类数。
接下来 n 行,每行两个整数 ci 与 qi (1 ≤ ci, qi ≤ 10^9),含义如上。
接下来一行一个正整数 k (1 ≤ k ≤ 2·10^5) ,表示顾客数。
接下来 k 个正整数 b1, b2, ..., bk (1 ≤ bj ≤ 10^9)。

Output
输出一行 k 个整数,表示第 i 个人买的 T-shirt。

Examples
Input
3
7 5
3 5
4 3
2
13 14
Output
2 3

Input
2
100 500
50 499
4
50 200 150 100
Output
1 2 2 1

@solution@

假如我们把人当作询问,T-shirt 当作元素,则至少我是想不出什么办法快速维护求出询问的。

但是反过来——我们按照 T-shirt 的优先级从大到小排序,把每个 T-shirt 当作一次修改,然后对人进行统一地修改,就很有戏了。
假如一个 T-shirt 的价格是 c,则我们的修改步骤就是先找出 >= c 的人,将这些人所拥有的钱减去 c,将这些人所拥有的 T-shirt 数量加上 1。

貌似可以用平衡树来 merge 和 split。但是注意,我们只能 merge 两个值域没有交集的平衡树,而减去 c 过后可能就产生了交集。
我们将 >= c 的人分为两类。第一类是 >= 2*c 的,这一部分减去 c 依然可以直接 merge;第二类是 < 2*c 的,这一类减去 c 过后只能一个个暴力插入。

因为第二类的人一定满足 c <= x < 2*c,每一次 x 至少折半,这样每个人只会被暴力插入 O(log)
于是就 O(nlog^2n) 的总复杂度。因为是 codeforces 所以能过。

@accepted code@

#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 200000;
struct treap{
    struct node{
        node *ch[2];
        int key, tg1;
        int sum, tg2;
        unsigned int pri;
    }pl[MAXN + 5], *ncnt, *NIL;
    #define mp make_pair
    #define fi first
    #define se second
    typedef pair<node*, node*> Droot;
    unsigned int get_rand() {return (rand() << 16) | rand();}
    treap() {
        NIL = ncnt = &pl[0];
        NIL->ch[0] = NIL->ch[1] = NIL;
        NIL->key = NIL->tg1 = NIL->sum = NIL->tg2 = 0;
        NIL->pri = -1;
    }
    node *newnode(int k) {
        node *p = (++ncnt);
        p->ch[0] = p->ch[1] = NIL;
        p->key = k, p->tg1 = p->sum = p->tg2 = 0;
        p->pri = get_rand();
        return p;
    }
    void maintain1(node *x, int k) {if( x != NIL ) x->key += k, x->tg1 += k;}
    void maintain2(node *x, int k) {if( x != NIL ) x->sum += k, x->tg2 += k;}
    void pushdown(node *rt) {
        if( rt->tg1 ) {
            maintain1(rt->ch[0], rt->tg1), maintain1(rt->ch[1], rt->tg1);
            rt->tg1 = 0;
        }
        if( rt->tg2 ) {
            maintain2(rt->ch[0], rt->tg2), maintain2(rt->ch[1], rt->tg2);
            rt->tg2 = 0;
        }
    }
    node *merge(node *x, node *y) {
        if( x == NIL ) return y;
        if( y == NIL ) return x;
        pushdown(x), pushdown(y);
        if( x->pri < y->pri ) {
            x->ch[1] = merge(x->ch[1], y);
            return x;
        }
        else {
            y->ch[0] = merge(x, y->ch[0]);
            return y;
        }
    }
    Droot split(node *rt, int k) {
        if( rt == NIL ) return mp(NIL, NIL);
        pushdown(rt);
        if( rt->key < k ) {
            Droot p = split(rt->ch[1], k);
            rt->ch[1] = p.fi; return mp(rt, p.se);
        }
        else {
            Droot p = split(rt->ch[0], k);
            rt->ch[0] = p.se; return mp(p.fi, rt);
        }
    }// < k, >= k
    node *insert(node *rt, node *x) {
        Droot p = split(rt, x->key);
        return merge(p.fi, merge(x, p.se));
    }
    void push(node *&rt, node *x) {
        if( x == NIL ) return ;
        pushdown(x);
        push(rt, x->ch[0]), push(rt, x->ch[1]);
        x->ch[0] = x->ch[1] = NIL;
        rt = insert(rt, x);
    }
    node *update(node *rt, int k) {
        Droot p = split(rt, k);
        if( p.se == NIL ) return merge(p.fi, p.se);
        p.se->key -= k, p.se->tg1 -= k;
        p.se->sum += 1, p.se->tg2 += 1;
        Droot q = split(p.se, k);
        if( q.fi != NIL ) push(p.fi, q.fi);
        return merge(p.fi, q.se);
    }
    void dfs(node *x) {
        if( x == NIL ) return ;
        pushdown(x);
        dfs(x->ch[0]), dfs(x->ch[1]);
    }
}T;
treap::node *nd[MAXN + 5], *rt;
struct Tshirt{
    int c, q;
    Tshirt(int _c=0, int _q=0):c(_c), q(_q) {}
    friend bool operator < (Tshirt a, Tshirt b) {
        return (a.q == b.q) ? a.c < b.c : a.q > b.q;
    }
}t[MAXN + 5];
int ans[MAXN + 5];
int read() {
    int x = 0; char ch = getchar();
    while( ch > '9' || ch < '0' ) ch = getchar();
    while( '0' <= ch && ch <= '9' ) x = 10*x + ch - '0', ch = getchar();
    return x;
}
int main() {
    int n = read(), k;
    srand(n ^ 0307);
    for(int i=1;i<=n;i++)
        t[i].c = read(), t[i].q = read();
    sort(t + 1, t + n + 1);
    k = read(), rt = T.NIL;
    for(int i=1;i<=k;i++)
        rt = T.insert(rt, nd[i] = T.newnode(read()));
    for(int i=1;i<=n;i++)
        rt = T.update(rt, t[i].c);
    T.dfs(rt);
    for(int i=1;i<=k;i++)
        printf("%d ", nd[i]->sum);
}

@details@

思路本身还是很巧妙的。
而且也印证了非旋 treap 是一种非常优美的数据结构,因为基本上没有什么实现难度。

标签:rt,node,ch,return,702F,NIL,int,codeforces,Shirts
来源: https://www.cnblogs.com/Tiw-Air-OAO/p/11693185.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有