zoukankan      html  css  js  c++  java
  • BZOJ 3932: [CQOI2015]任务查询系统 | 主席树练习题

    题目:

    洛谷也能评测


    题解:

    De了好长时间BUG发现是自己sort前面有一行for没删,气死.

    题目询问第x秒时候前k小的P值之和.

    朴素想法:

    我们可以把P值离散化,然后对于每个时刻建一棵定义域是离散化后P值的线段树

    每个节点维护了这个节点代表区间的任务个数和这些任务离散化之前的P值之和,

    对于每个在这个时间段的任务,插入,即在p位置单点修改

    询问就是类似二叉查找树的写法

    高级想法:

    首先把一段任务拆成两个:添加和删除,用三元组(t,p,d)表示,d=1表示插入,d=-1表示删除

    对于第maxt棵线段树,我们把操作按t值排序之后进行,

    这岂不是就变成可以一棵可以访问历史版本的线段树---主席树了!

    那么写棵主席树,插入操作按t排序就O**K了

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    typedef long long ll; 
    #define N 200100
    #define Nlogn N*20
    using namespace std;
    ll root[Nlogn],n,A,B,C,pre=1,m,b[N],K,pcnt,opcnt,lim;
    struct node
    {
        ll lc,rc,sum,val;
    }t[Nlogn];
    struct Op
    {
        ll t,p,d;
        bool operator < (const Op &a) const{return t<a.t;}
    }op[2*N];
    ll read()
    {
        ll ret=0,neg=1;char j=getchar();
        for (;j>'9' || j<'0';j=getchar())
        if (j=='-') neg=-1;
        for (;j>='0' && j<='9';j=getchar())
        ret=ret*10+j-'0';
        return ret*neg;
    }
    void Insert(ll y,ll &x,ll l,ll r,ll p,ll d)
    {
        t[x=++pcnt]=t[y];
        t[x].sum+=d;t[x].val+=b[p]*d;
        if (l==r) return;
        ll mid=l+r>>1;
        if (p<=mid) Insert(t[y].lc,t[x].lc,l,mid,p,d);
        else Insert(t[y].rc,t[x].rc,mid+1,r,p,d);
    }
    ll query(ll u,ll l,ll r,ll k)
    {
        ll mid,ret=0;
        while (l<r)
        {
            if (t[u].sum==0) return ret;
                mid=l+r>>1;    
                if (k<=t[t[u].lc].sum) r=mid,u=t[u].lc;
                else k-=t[t[u].lc].sum,ret+=t[t[u].lc].val,l=mid+1,u=t[u].rc;
        }
        return ret+b[l]*k;
    }
    int getroot(int x)
    {
        return root[x-1]=(root[x-1]!=0 || x==1)?root[x-1]:getroot(x-1);
    }
    int main()
    {
        m=read(),n=read();
        for (ll i=1,s,e,p;i<=m;i++)
        {
            s=read(),e=read(),p=read();
            op[++opcnt].t=s,b[opcnt]=op[opcnt].p=p,op[opcnt].d=1;
              op[++opcnt].t=e+1,b[opcnt]=op[opcnt].p=p,op[opcnt].d=-1;
        }
        //离散化 
        sort(b+1,b+1+opcnt);
        lim=unique(b+1,b+1+opcnt)-b-1;
        for (ll i=1;i<=opcnt;i++)
            op[i].p=lower_bound(b+1,b+lim+1,op[i].p)-b;
        //按操作时间插入节点 
          sort(op+1,op+1+opcnt);
        for (ll i=1,j=1;i<=opcnt;i++)
        {
               if (root[op[i].t]==0) root[op[i].t]=getroot(op[i].t);
            Insert(root[op[i].t],root[op[i].t],1,lim+10,op[i].p,op[i].d);
        }
        for (ll i=1,x;i<=n;i++)
        {
               x=read(),A=read(),B=read(),C=read();
               K=1+(A*pre+B)%C;
               printf("%lld
    ",pre=query(root[x],1,lim+10,K));
        }   
        return 0;
    }
  • 相关阅读:
    (转)导弹跟踪算法
    中文linux安装oracle界面乱码解决方案
    linux下创建oracle表空间
    [INS-20802] Oracle Net Configuration Assistant failed
    Centos6.5下Oracle 11g R2安装过程
    设置MYSQL数据库编码为UTF-8
    如何在linux系统中设置静态ip地址
    Oracle Net Configuration Assistant failed异常的解决方案
    解决安装oracle11g r2时提示pdksh conflicts with ksh-20100621-2.el6.i686问题
    CentOS增加swap分区大小
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8150992.html
Copyright © 2011-2022 走看看