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;
}
posted @ 2020-07-23 08:31  yugyppah656  阅读(150)  评论(0编辑  收藏  举报