zoukankan      html  css  js  c++  java
  • BZOJ 3932: [CQOI2015]任务查询系统

    http://www.lydsy.com/JudgeOnline/problem.php?id=3932

    主席树(可持久化线段树)模板题。

    然而我太了,调了1h+,发现询问区间前k大的时候,忘了对重复元素个数判断,导致WA。

    做法:把每个任务拆成两个事件,按照时间排序,从前往后建主席树。

    然后对每个询问查询区间前k大之和。

    贴个版子(指针):

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN=300005, MAXS=1e7+5;
    int M, N, tot, id[MAXN];
    int cnt[MAXN], num[MAXN];
    struct Node
    {
        Node *lc, *rc;
        int n, l, r;
        ll s;
        inline void up(){
            n=lc->n+rc->n;
            s=lc->s+rc->s;
        }
        ll qry(int k){
            if(l==r) return (ll)num[l]*min(k, n);
            if(k<=lc->n) return lc->qry(k);
            else return lc->s+rc->qry(k-lc->n);
        }
    }tr[MAXS], *rt[MAXN];
    void upd(Node *&c, Node *t, int x){
        c=&tr[tot++];
        c->l=t->l, c->r=t->r;
        if(c->l==c->r){
            c->n=cnt[x];
            c->s=(ll)cnt[x]*num[x];
            return;
        }
        int mid=(c->l+c->r)>>1;
        if(x<=mid){
            upd(c->lc, t->lc, x);
            c->rc=t->rc;
            c->up();
        }else{
            c->lc=t->lc;
            upd(c->rc, t->rc, x);
            c->up();
        }
    }
    void build(Node *&x, int l, int r)
    {
        x=&tr[tot++];
        x->l=l, x->r=r;
        if(l==r) return;
        int mid=(l+r)>>1;
        build(x->lc, l, mid);
        build(x->rc, mid+1, r);
    }
    struct Evt{
        int x, t, p;
        bool operator<(const Evt &e) const {return x<e.x;}
    }E[MAXN];
    int main()
    {
        scanf("%d%d", &M, &N);
        for(int i=0; i<M; ++i){
            int s, e, p; scanf("%d%d%d", &s, &e, &p);
            E[i].x=s; E[i].t=1;
            E[i+M].x=e+1; E[i+M].t=0;
            E[i].p=E[i+M].p=p;
            num[i+1]=p;
        }
        sort(num+1, num+M+1); int nt=unique(num+1, num+M+1)-(num+1);
        for(int i=0; i<M; ++i){
            E[i].p=E[i+M].p=lower_bound(num+1, num+1+nt, E[i].p)-num;
        }
        M<<=1;
        sort(E, E+M); E[M++].x=N+1;
        build(rt[0], 1, nt);
        int last=0;
        for(int i=0; i<M; ++i){
            if(E[i].x>last){
                id[last]=i;
                last=E[i].x;
            }
            if(E[i].x>N) break;
            if(E[i].t) cnt[E[i].p]++;
            else cnt[E[i].p]--;
            upd(rt[i+1], rt[i], E[i].p);
        }
        for(int i=1; i<=N; ++i) if(!id[i]) id[i]=id[i-1];
        ll pre=1;
        for(int i=0; i<N; ++i){
            int x, a, b, c;
            scanf("%d%d%d%d", &x, &a, &b, &c);
            a=1+((ll)a*pre+b)%c;
            printf("%lld
    ", (pre=rt[id[x]]->qry(a)));
        }
        return 0;
    }
    
  • 相关阅读:
    硬盘安装windows2008的方法
    win7,win2008R2的vs2008 破解方法
    学习正则表达式
    C#里内置的DateTime基本功能
    jQuery Ajax 实例 全解析
    TreeView 部署后不能显示图标、js出错原因
    js 操作Listbox js 获取Listbox选择的值的代码
    ajax调用后台Datatable
    转:jquery刷新页面 页面跳转 js常用函数
    GridView多行表头的实现
  • 原文地址:https://www.cnblogs.com/will7101/p/6523370.html
Copyright © 2011-2022 走看看