zoj 3299 线段树

来源:互联网 发布:zip在linux下解压 编辑:程序博客网 时间:2024/05/23 15:06

题意:从空中落下的一排一排的砖头落在空中的线段上

然后会累计 


这题有点扫描线的意思 也是把线段搞成点树

是个好题啊 但是为什么需要开100W?换了很多姿势都过不了!

原因

数组然后开大一点马上MLE  开小马上WA (不能全用左移啊 只能乖乖*10了)

然后献上两种姿势:

 最土但是最易于理解的双标记法:

#include<string.h>#include<stdio.h>#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define maxn 100111#define LL long long#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)int set[maxn<<4];LL sum[maxn<<4];LL add[maxn*10];int x[maxn<<2];void up(int rt,int l,int r){sum[rt]=sum[ls]+sum[rs];}void down(int rt,int l,int r){    if(set[rt]!=-1){        sum[ls]=sum[rs]=0;add[ls]=add[rs]=0;        set[ls]=set[rs]=1;        set[rt]=-1;    }    if(add[rt]){        sum[ls]+=(LL)((x[mid+1]-x[l])*add[rt]);        sum[rs]+=(LL)((x[r+1]-x[mid+1])*add[rt]);        add[ls]+=add[rt];        add[rs]+=add[rt];        add[rt]=0;    }}void ins(int rt,int l,int r,int L,int R){    if(L<=l&&r<=R){        sum[rt]+=(LL)(x[r+1]-x[l]);        add[rt]++;        return ;    }    down(rt,l,r);    if(L<=mid)ins(ls,l,mid,L,R);    if(mid<R)ins(rs,mid+1,r,L,R);    up(rt,l,r);}void _set(int rt,int l,int r,int L,int R){    if(L<=l&&r<=R){        set[rt]=1;sum[rt]=add[rt]=0;        return ;    }    down(rt,l,r);    if(L<=mid)_set(ls,l,mid,L,R);    if(mid<R)_set(rs,mid+1,r,L,R);    up(rt,l,r);}LL query(int rt,int l,int r,int L,int R){    //    printf("%d %d %d\n",l,r,sum[rt]);//    if(set[rt]!=-1)return 0;    if(L<=l&&r<=R)return sum[rt];    down(rt,l,r);    LL res=0;    if(L<=mid)res+=query(ls,l,mid,L,R);    if(mid<R)res+=query(rs,mid+1,r,L,R);    return res;}int ll[maxn<<1],rr[maxn<<1];int n,m,cnt,tmp;struct line{    int l,r,h;    int id;    line(int l=0,int r=0,int h=0):l(l),r(r),h(h){}}e[maxn];LL ans[maxn];int cmp(line x,line y){return x.h>y.h;}int main(){    while(~scanf("%d%d",&n,&m)){                memset(set,-1,sizeof set);        memset(sum,0,sizeof sum);        memset(add,0,sizeof add);        cnt=0;        for(int i=0;i<n;++i){            scanf("%d%d",&ll[i],&rr[i]);            x[cnt++]=ll[i];x[cnt++]=rr[i];        }                for(int i=0;i<m;++i){            scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].h);            x[cnt++]=e[i].l;x[cnt++]=e[i].r;            e[i].id=i;        }                sort(x,x+cnt);        tmp=(int)(unique(x,x+cnt)-x);                //        for(int i=0;i<tmp;++i)printf("%d ",x[i]);printf("\n");                sort(e,e+m,cmp);                for(int i=0;i<n;++i){            ll[i]=(int)(lower_bound(x,x+tmp,ll[i])-x);            rr[i]=(int)(lower_bound(x,x+tmp,rr[i])-x)-1;            ins(1,0,tmp-1,ll[i],rr[i]);        }                for(int i=0;i<m;++i){            e[i].l=(int)(lower_bound(x,x+tmp,e[i].l)-x);            e[i].r=(int)(lower_bound(x,x+tmp,e[i].r)-x)-1;//            printf("%d %d\n",e[i].l,e[i].r);            ans[e[i].id]=query(1,0,tmp-1,e[i].l,e[i].r);            _set(1,0,tmp-1,e[i].l,e[i].r);        }        for(int i=0;i<m;++i)printf("%lld\n",ans[i]);        printf("\n");            }    return 0;}

比较厉害的标记不下传法:

#include<string.h>#include<stdio.h>#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define maxn 100111#define LL long long#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)int set[maxn<<4];LL sum[maxn<<4];LL add[maxn*10];int x[maxn<<2];void up(int rt,int l,int r){sum[rt]=sum[ls]+sum[rs];}void down(int rt,int l,int r){    if(add[rt]){        sum[ls]+=(LL)((x[mid+1]-x[l])*add[rt]);        sum[rs]+=(LL)((x[r+1]-x[mid+1])*add[rt]);        add[ls]+=add[rt];        add[rs]+=add[rt];        add[rt]=0;    }}void ins(int rt,int l,int r,int L,int R){    if(L<=l&&r<=R){        sum[rt]+=(LL)(x[r+1]-x[l]);        add[rt]++;        return ;    }    down(rt,l,r);    if(L<=mid)ins(ls,l,mid,L,R);    if(mid<R)ins(rs,mid+1,r,L,R);    up(rt,l,r);}LL query(int rt,int l,int r,int L,int R){    //    printf("%d %d %d\n",l,r,sum[rt]);    if(set[rt])return 0;    if(L<=l&&r<=R){        set[rt]=1;        LL tmp=sum[rt];        sum[rt]=0;        return tmp;    }    down(rt,l,r);    LL res=0;    if(L<=mid)res+=query(ls,l,mid,L,R);    if(mid<R)res+=query(rs,mid+1,r,L,R);    up(rt,l,r);    return res;}int ll[maxn<<1],rr[maxn<<1];int n,m,cnt,tmp;struct line{    int l,r,h;    int id;    line(int l=0,int r=0,int h=0):l(l),r(r),h(h){}}e[maxn];LL ans[maxn];int cmp(line x,line y){return x.h>y.h;}int main(){    while(~scanf("%d%d",&n,&m)){                memset(set,0,sizeof set);        memset(sum,0,sizeof sum);        memset(add,0,sizeof add);        cnt=0;        for(int i=0;i<n;++i){            scanf("%d%d",&ll[i],&rr[i]);            x[cnt++]=ll[i];x[cnt++]=rr[i];        }                for(int i=0;i<m;++i){            scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].h);            x[cnt++]=e[i].l;x[cnt++]=e[i].r;            e[i].id=i;        }                sort(x,x+cnt);        tmp=(int)(unique(x,x+cnt)-x);                sort(e,e+m,cmp);                for(int i=0;i<n;++i){            ll[i]=(int)(lower_bound(x,x+tmp,ll[i])-x);            rr[i]=(int)(lower_bound(x,x+tmp,rr[i])-x)-1;            ins(1,0,tmp-1,ll[i],rr[i]);        }                for(int i=0;i<m;++i){            e[i].l=(int)(lower_bound(x,x+tmp,e[i].l)-x);            e[i].r=(int)(lower_bound(x,x+tmp,e[i].r)-x)-1;            ans[e[i].id]=query(1,0,tmp-1,e[i].l,e[i].r);        }        for(int i=0;i<m;++i)printf("%lld\n",ans[i]);        printf("\n");    }    return 0;}


0 0
原创粉丝点击