zoukankan      html  css  js  c++  java
  • bzoj3932 [CQOI2015]任务查询系统——主席树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3932

    第二道主席树!本来想自己手胡一下,但是还是写不下去了...

    参考博客:https://www.cnblogs.com/CQzhangyu/p/6295579.html

    就是对每个时间节点建一棵权值线段树,节点太多所以开成主席树;

    WA了好久,竟然是错在二分的地方了???看了半天还是不知道为什么错,那个写法已经用了好久了啊...

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const maxn=2e5+5;
    ll n,m,ls[maxn*40],rs[maxn*40],siz[maxn*40],tot,rt[maxn],cnt;
    ll sum[maxn*40],ans,t[maxn];
    struct N{ll t,v,k;}p[maxn];
    bool cmp1(N x,N y){return x.v<y.v;}
    bool cmp2(N x,N y){return x.t<y.t;}
    void pushup(ll x)
    {
        siz[x]=siz[ls[x]]+siz[rs[x]];
        sum[x]=sum[ls[x]]+sum[rs[x]];
    }
    void insert(ll u,ll &v,ll l,ll r,ll pos,ll val)
    {
        v=++cnt;
        if(l==r)
        {
            siz[v]=siz[u]+val;
            sum[v]=sum[u]+t[pos]*val;
            return;
        }
        ls[v]=ls[u]; rs[v]=rs[u]; sum[v]=sum[u]; siz[v]=siz[u];
        ll mid=((l+r)>>1);
        if(pos<=mid)rs[v]=rs[u],insert(ls[u],ls[v],l,mid,pos,val);
        else ls[v]=ls[u],insert(rs[u],rs[v],mid+1,r,pos,val);
        pushup(v);
    }
    ll query(ll x,ll l,ll r,ll pos)
    {
        if(l==r)return t[l]*pos;//*pos!
        ll mid=((l+r)>>1);
        if(siz[ls[x]]>=pos)return query(ls[x],l,mid,pos);
        else return sum[ls[x]]+query(rs[x],mid+1,r,pos-siz[ls[x]]);
    }
    int main()
    {
        scanf("%lld%lld",&m,&n);
        for(ll i=1,x,y,z;i<=m;i++)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            p[i*2-1].t=x; p[i*2].t=y+1; p[i*2-1].v=p[i*2].v=z;
            p[i*2-1].k=1; p[i*2].k=-1;
        }
        sort(p+1,p+2*m+1,cmp1);//v
        for(ll i=1;i<=2*m;i++)//离散化 
        {
            if(p[i].v!=t[tot])t[++tot]=p[i].v;
            p[i].v=tot;
        }
        sort(p+1,p+2*m+1,cmp2);//t
        for(ll i=1;i<=2*m;i++)//权值线段树 
            insert(rt[i-1],rt[i],1,tot,p[i].v,p[i].k);
        ans=1;
        for(ll i=1,x,a,b,c,k;i<=n;i++)
        {
            scanf("%lld%lld%lld%lld",&x,&a,&b,&c);
            k=1+(a*ans+b)%c;
    //        ll l=1,r=2*m+1,nw;
    //        while(l<=r)//二分找到该节点线段树 
    //        {
    //            ll mid=((l+r)>>1);
    //            if(p[mid].t<=x)nw=mid,l=mid+1;
    //            else r=mid-1;
    //        }
            ll l=1,r=2*m+1,mid;//写成r=2*n-1竟然也过了,数据... 
            while(l<r)
            {
                mid=l+r>>1;
                if(p[mid].t<=x) l=mid+1;
                else r=mid;
            }
            ll nw=l-1;
            if(siz[rt[nw]]<=k)ans=sum[rt[nw]];
            else ans=query(rt[nw],1,tot,k);
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Javascript快速入门(上篇)
    Linux快速入门01-基础概念
    正则表达式快速入门
    Sublime快速入门
    centos 6.5 git 服务器的配置(入门级)
    centos6.5 网卡的处理
    centos 6.5 u盘 安装问题 :vesamenu.c32: Not a COM32R image
    ubuntu 14.04 对exfat的支持
    [转]ubuntu 14.04 如何开启和关闭触控板
    ubuntu 下mongodb安装
  • 原文地址:https://www.cnblogs.com/Zinn/p/9337876.html
Copyright © 2011-2022 走看看