首页 > 其他分享 >额额额~主席树

额额额~主席树

时间:2022-08-30 17:47:52浏览次数:48  
标签:额额额 cnt int 个数 sum tr 区间 主席

题意:

给定一个长度为n的序列和一个正整数m,有若干个询问,每次询问一个区间[l, r],请问区间是否存在k个数的和 >= m。

写的时候:没注意到是不用连续的k个数,用前缀和写样例过了,但是后面的测试有错 正解: 要使区间内满足k个数>=m,我们只需要挑出最大的k的数即可。如何维护区间最大k个数呢?这不是主席树的板子嘛!不了解板子的可以看这篇 [https://zhuanlan.zhihu.com/p/558921818](https://zhuanlan.zhihu.com/p/558921818)
struct Node
{
    int l, r;
    int cnt;
    int sum;
}tr[N << 5];
int n, m, idx , root[N], a[N], k, x;

void pushup(int u)
{
    tr[u].cnt = tr[tr[u].l].cnt + tr[tr[u].r].cnt;
    tr[u].sum = tr[tr[u].l].sum + tr[tr[u].r].sum;
}

void insert(int &u, int v, int l, int r, int x)
{
    u = ++ idx;
    tr[u] = tr[v];
    tr[u].cnt ++ ;
    tr[u].sum += x;
    if(l == r) return ;
    int mid = l + r >> 1;
    if(x <= mid) insert(tr[u].l, tr[v].l, l, mid, x);
    else insert(tr[u].r, tr[v].r, mid + 1, r, x);
    pushup(u);
}

int query(int p, int q, int l, int r, int k)
{
    if(l == r) return l;
    int cnt = tr[tr[q].r].cnt - tr[tr[p].r].cnt;
    int mid = l + r >> 1;
    if(k <= cnt) return query(tr[p].r, tr[q].r, mid + 1, r, k);
    if(k > cnt) return tr[tr[q].r].sum - tr[tr[p].r].sum + query(tr[p].l, tr[q].l, l, mid, k - cnt);
}

int main()
{
    cin >> n >> m >> k >> x;
    for(int i = 1 ; i <= n ; i ++ )
    {
        cin >> a[i];
        insert(root[i], root[i - 1], 0, INF, a[i]);
    }
    
    for(int i = 1 ; i <= m ; i ++ )
    {
        int l, r;
        cin >> l >> r;
        cout << (query(root[l - 1], root[r], 0, INF, k) >= x ? "Y" : "N") << endl;
    }
    
    return 0;
}

标签:额额额,cnt,int,个数,sum,tr,区间,主席
From: https://www.cnblogs.com/win-dy/p/16640206.html

相关文章

  • P3963 [TJOI2013] 奖学金——主席树
    最后翻看题解才发现可以不用主席树……就当是练习好了基本思路本题要让中位数最大,如果是最小值最大我们可以用二分答案,二中位数最大可不可以呢?显然是不行的,所以我们枚举......
  • [学习笔记]主席树
    1.静态主席树主席树,即可持久化线段树,又称函数式线段树,是重要的可持久化数据结构之一。所谓可持久化,是指可以回溯到历史版本。主席树的本质,就是在有数据更新时,在基准线段......
  • 主席树小专题
    静态主席树:https://www.cnblogs.com/LonecharmRiver/articles/9087536.html看看就好动态主席树:https://blog.csdn.net/WilliamSun0122/article/details/77885781在里面......