hdu4973 线段树

来源:互联网 发布:网络推广广告 编辑:程序博客网 时间:2024/06/04 19:14

题意:给定的序列 有两个操作 1将其中一段加倍 2询问段中的最长相等数字是多少

解法:直接上线段树就可以了 但是-》边界问题比较麻烦 有两种做法 一种在更新的时候直接判定边界,另外一种则是选定完边界再进行更新,题解的说法里面是第二种啊,但是比赛的时候不敢敲,怕码力不够啊。有点后悔的


首先是麻烦的写法:

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)#define ll __int64#define maxn 55555ll sum[maxn<<2],mul[maxn<<2],ma[maxn<<2];void up(int rt,int l,int r){    sum[rt]=sum[ls]+sum[rs];    ma[rt]=max(ma[ls],ma[rs]);}void down(int rt,int l,int r){    if(mul[rt]){        sum[ls]<<=mul[rt];        sum[rs]<<=mul[rt];        ma[ls]<<=mul[rt];        ma[rs]<<=mul[rt];        mul[ls]+=mul[rt];        mul[rs]+=mul[rt];        mul[rt]=0;    }}void build(int rt,int l,int r){    mul[rt]=0;    if(l==r){        sum[rt]=ma[rt]=(ll)1;        return ;    }    build(ls,l,mid);    build(rs,mid+1,r);    up(rt,l,r);}int queryl(int rt,int l,int r,ll w){    if(l==r)return l;    down(rt,l,r);        if(sum[ls]>=w){        return queryl(ls,l,mid,w);    }else return queryl(rs,mid+1,r,w-sum[ls]);}void ins(int rt,int l,int r,int L,int R){    if(L<=l&&r<=R){        sum[rt]<<=1;        ma[rt]<<=1;        mul[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 ins_s(int rt,int l,int r,int L,int R,ll w){    if(L<=l&&r<=R){        sum[rt]+=w;        ma[rt]+=w;        return ;    }down(rt,l,r);    if(L<=mid)ins_s(ls,l,mid,L,R,w);    if(mid<R)ins_s(rs,mid+1,r,L,R,w);    up(rt,l,r);}ll querys(int rt,int l,int r,int L,int R){    if(L<=l&&r<=R){        return sum[rt];    }down(rt,l,r);    ll res=0;    if(L<=mid)res+=querys(ls,l,mid,L,R);    if(mid<R)res+=querys(rs,mid+1,r,L,R);    return res;}ll query(int rt,int l,int r,int L,int R){    if(L<=l&&r<=R)return ma[rt];    down(rt,l,r);    ll res=0;    if(L<=mid)res=max(res,query(ls,l,mid,L,R));    if(mid<R)res=max(res,query(rs,mid+1,r,L,R));    return res;}int n,m;char op[111];int main(){    int _;scanf("%d",&_);    for(int z=1;z<=_;++z){        scanf("%d%d",&n,&m);        build(1,1,n);ll l,r;        printf("Case #%d:\n",z);        while(m--){            scanf("%s%I64d%I64d",op,&l,&r);            if(l>r)swap(l,r);            int lf=queryl(1,1,n,l);            int ri=queryl(1,1,n,r);            ll lsum=querys(1,1,n,1,lf),rsum;            if(ri>1)rsum=querys(1,1,n,1,ri-1);            else rsum=0;            //            printf("%d %d %lld %lld\n",lf,ri,lsum,rsum);            if(*op=='D'){                if(lf==ri){                    ins_s(1,1,n,lf,lf,r-l+1);                }else{                    if(lf+1<=ri-1)ins(1,1,n,lf+1,ri-1);                    ins_s(1,1,n,lf,lf,lsum-l+1);                    ins_s(1,1,n,ri,ri,r-rsum);                }            }            else{                if(lf==ri){                    printf("%I64d\n",r-l+1);                }else{                    ll maxx=0;                    if(lf+1<=ri-1)maxx=max(maxx,query(1,1,n,lf+1,ri-1));                    maxx=max(maxx,lsum-l+1);                    maxx=max(maxx,r-rsum);                    printf("%I64d\n",maxx);                }            }        }    }    return 0;}

其次是比较简洁的:

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)#define ll __int64#define maxn 55555int scan(){    int res=0,ch;    while(!((ch= getchar())>='0'&&ch<='9')){        if(ch==EOF)return 1<<30;    }    res=ch-'0';    while((ch=getchar())>='0'&&ch<='9')        res=res*10+(ch-'0');    return res;}ll sum[maxn<<2],mul[maxn<<2],ma[maxn<<2];void up(int rt,int l,int r){    sum[rt]=sum[ls]+sum[rs];    ma[rt]=max(ma[ls],ma[rs]);}void down(int rt,int l,int r){    if(mul[rt]){        sum[ls]<<=mul[rt];        sum[rs]<<=mul[rt];        ma[ls]<<=mul[rt];        ma[rs]<<=mul[rt];        mul[ls]+=mul[rt];        mul[rs]+=mul[rt];        mul[rt]=0;    }}void build(int rt,int l,int r){    mul[rt]=0;    if(l==r){        sum[rt]=ma[rt]=(ll)1;        return ;    }    build(ls,l,mid);    build(rs,mid+1,r);    up(rt,l,r);}void insr(int rt,int l,int r,ll L,ll R){    if(l==r){        ma[rt]=sum[rt]+=R-L+1;        return ;    }else if(R-L+1==sum[rt]){        sum[rt]<<=1;ma[rt]<<=1;mul[rt]++;        return ;    }down(rt,l,r);    if(sum[ls]>=R)insr(ls,l,mid,L,R);    else if(sum[ls]<L)insr(rs,mid+1,r,L-sum[ls],R-sum[ls]);    else{        insr(rs,mid+1,r,1,R-sum[ls]);        insr(ls,l,mid,L,sum[ls]);    }    up(rt,l,r);}ll queryr(int rt,int l,int r,ll L,ll R){    if(l==r)return R-L+1 ;    if(R-L+1==sum[rt])return ma[rt];    down(rt,l,r);    if(sum[ls]>=R)return queryr(ls,l,mid,L,R);    if(sum[ls]<L)return queryr(rs,mid+1,r,L-sum[ls],R-sum[ls]);    return max(queryr(ls,l,mid,L,sum[ls]),queryr(rs,mid+1,r,1,R-sum[ls]));}int n,m;char op[111];int main(){    int _;scanf("%d",&_);    for(int z=1;z<=_;++z){        scanf("%d%d",&n,&m);                build(1,1,n);ll l,r;        printf("Case #%d:\n",z);        while(m--){            scanf("%s%I64d%I64d",op,&l,&r);            if(*op=='D'){                insr(1,1,n,l,r);            }            else{                printf("%I64d\n",queryr(1,1,n,l,r));            }        }    }    return 0;}


0 0
原创粉丝点击