• hdu5140 Hun Gui Wei Company题解 主席树


    题目链接

    这个题还是比较模板的。等级和年限这两个参数,一个当成下标,一个当成值域(应该是这么叫的吧)。

    假设以level为下标建立主席树,age作为值域,那我们可以把所有员工的level离散化。因为这个题强制在线,我们没有办法把查询的level离散化,但是我们可以每次二分,找到这个询问对应着的范围。我偷懒没有离散化age,写的动态开点。

    需要注意的几个点:

    • 模板要写对,我因为这个调了一整天。
    • 还有二分的问题,算是个小套路,大家都知道lower_bound(a+1,a+n+1,x)-a,二分最后一个<=x的数可以用upper_bound(a+1,a+n+1,x)-a-1。这两个式子的取值范围分别是\([1,n+1]\)\([0,n]\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    #define forg(i,x) for(int i=first[x];i;i=nxt[i])
    #define forl(z,i,x) for(int i=z.first[x],y=z.to[i];i;i=z.nxt[i],y=z.to[i])
    #define uu unsigned
    #define fi first
    #define se second
    #define ran() ((unsigned)rand())
    #define lam(z,k) [&](const z &a,const z &b){ return k; }
    #define od(x) ((x)&1)
    #define ev(x) (od(x)^1)
    
    #define lson(x) tr[x].lson
    #define rson(x) tr[x].rson
    const int mxn=1e5+3,mxm=mxn,siz=1e9;const long long cc=1e17;
    int n,m,nn;
    struct worker{ 
        int gz,dj,tm;//工资 等级 时间
    }a[mxn];
    int lsd[mxn];
    inline int getls(int x){
        return lower_bound(lsd+1,lsd+nn+1,x)-lsd;
    }
    class zxs{
        public:
        struct a_w{
            int lson,rson;
            long long sum;
        }tr[mxn*50];
        int RT[mxn],tot;
        inline void clear(){
            memset(RT,0,sizeof(RT));
            for(int i=1;i<=tot;++i)tr[i].sum=lson(i)=rson(i)=0;
            tot=0;
        }
        inline void dadd(int &p,int pre,int l,int r,int pc,int kc){
    //单点修改
            int mid=(l+r)>>1;
            if(p==0||p==pre){
                p=++tot; if(pre)tr[p]=tr[pre];
                
            }
            if(l==r)return tr[p].sum+=kc,void();
            if(pc<=mid)dadd(lson(p),lson(pre),l,mid,pc,kc);
            else dadd(rson(p),rson(pre),mid+1,r,pc,kc);
            pushup(p);
        }
        inline void pushup(int x){
            tr[x].sum=tr[lson(x)].sum+tr[rson(x)].sum;
        }
        inline long long ask(int x1,int x2,int l,int r,int lc,int rc){
            int mid=(l+r)>>1;
            if(!x1&&!x2)return 0;
            if(lc<=l&&r<=rc)return tr[x2].sum-tr[x1].sum;
            long long res=0;
            if(lc<=mid)res+=ask(lson(x1),lson(x2),l,mid,lc,rc);
            if(rc>mid)res+=ask(rson(x1),rson(x2),mid+1,r,lc,rc);
            return res;
        }
    }seg;
    
    class hah{public:void a(){b();}void b(){a();}}emm;
    inline int getdj2(int x){
        int l=0,r=nn,mid;
        while(l!=r){
            mid=(l+r+1)>>1;
            if(lsd[mid]<=x)l=mid;
            else r=mid-1;
        }
        return l;
    }
    
    int main(){
        while(~scanf("%d",&n)){
            seg.clear();
            for(int i=1;i<=n;++i)scanf("%d%d%d",&a[i].gz,&a[i].dj,&a[i].tm),lsd[i]=a[i].dj;
            scanf("%d",&m);
            sort(lsd+1,lsd+n+1);nn=unique(lsd+1,lsd+n+1)-(lsd+1);
            for(int i=1;i<=n;++i)a[i].dj=getls(a[i].dj);
            sort(a+1,a+n+1,lam(worker,a.dj<b.dj));
            
            
            for(int i=1,p=1;i<=nn&&p<=n;++i){
                int &kk=seg.RT[i];
                for(;a[p].dj==i&&p<=n;++p){
                    seg.dadd(kk,seg.RT[i-1],1,siz+1,a[p].tm+1,a[p].gz);
                }
                if(!kk)kk=seg.RT[i-1];//这句可以省略,因为离散化以后是连续的
            }
            
            lsd[0]=-233,lsd[nn+1]=siz+233;
            
            long long lstans=0;
    
            for(int i=1;i<=m;++i){
                static long long dj1,dj2,tm1,tm2;scanf("%lld%lld%lld%lld",&dj1,&dj2,&tm1,&tm2);
                dj1+=lstans,dj2-=lstans,tm1+=lstans,tm2-=lstans;
                if(dj1>dj2)swap(dj1,dj2);if(tm1>tm2)swap(tm1,tm2);
                dj1=max(dj1,0ll),tm1=max(tm1,0ll),dj2=min(dj2,(long long)siz),tm2=min(tm2,(long long)siz);
                if(dj1>dj2){puts("0");lstans=0;continue;}//特判
                int aa=dj1,bb=dj2;
                dj1=getls(dj1),dj2=upper_bound(lsd+1,lsd+nn+1,dj2)-lsd-1;//getdj2(dj2)
                if(!(lsd[dj1]>=aa&&lsd[dj1-1]<aa && lsd[dj2]<=bb&&lsd[dj2+1]>bb))return puts("whatawht"),emm.a(),33333;
    //检查二分的结果是否合法 这句不加也可以
                // first>=dj1 last<=dj2
                
                if(dj1>dj2||tm1>tm2){puts("0");lstans=0;continue;}//特判
                printf("%lld\n",lstans= seg.ask(seg.RT[dj1-1],seg.RT[dj2],1,siz+1,tm1+1,tm2+1));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    python自定义ORM并操作数据库
    python 元类理解
    Python中type()详解:动态创建类
    Centos7安装教程
    数据库建模:学生信息系统搭建实验
    数据库索引、视图与触发器
    用python批量插入数据到数据库中
    制作一个简单的部门员工知识分享的python抽取脚本
    【Mybatis】XML配置实现增删改查
    NIO,AIO,BIO
  • 原文地址:https://www.cnblogs.com/happyguy/p/13364252.html
Copyright © 2020-2023  润新知