nyoj1068 ST 线段树

来源:互联网 发布:社交网络的利弊 英文 编辑:程序博客网 时间:2024/05/08 23:13

题目链接
线段树查询区间和以及区间奇数个数。
区间和很好求,很快就写好了,区间奇数个数写起来麻烦一点,除了查询的时候需要lazy操作,更新的时候也需要lazy操作。
直接上代码:

#include<stdio.h>#include<string.h>#define ll long long#define maxn 10010struct stu{    ll l,r,mid,lazysum,odd,sum,lazyodd;  } w[maxn<<2];void build(ll l,ll r,ll tr)   //建树{    w[tr].mid=(l+r)>>1;    w[tr].l=l,w[tr].r=r,w[tr].odd=0,w[tr].lazysum=0,w[tr].lazyodd=0;    if(l==r)        scanf("%lld",&w[tr].sum),w[tr].odd=w[tr].sum&1;    else    {        build(l,w[tr].mid,tr<<1),build(w[tr].mid+1,r,tr<<1|1);        w[tr].sum=w[tr<<1].sum+w[tr<<1|1].sum;        w[tr].odd=w[tr<<1].odd+w[tr<<1|1].odd;    }}void update(ll x,ll y,ll z,ll tr)  //更新{    if(w[tr].lazyodd&&w[tr].l!=w[tr].r)  //若有lazyodd,且不是叶子节点    {        w[tr<<1].lazyodd^=1,w[tr<<1|1].lazyodd^=1;  //子节点的lazyodd若为0,就变成1,若为1,就变成0        w[tr<<1].odd=w[tr<<1].r-w[tr<<1].l+1-w[tr<<1].odd;//无论子节点的lazyodd是否为1,均更新子节点的odd个数        w[tr<<1|1].odd=w[tr<<1|1].r-w[tr<<1|1].l+1-w[tr<<1|1].odd;        w[tr].lazyodd=0;   //向子节点传递lazyodd后,清零    }    if(w[tr].l==x&&w[tr].r==y)    {        w[tr].lazysum+=z;  //更新lazysum        w[tr].sum+=(y-x+1)*z;           if(z&1)            w[tr].lazyodd^=1,w[tr].odd=w[tr].r-w[tr].l+1-w[tr].odd;  //若要加的数为奇数,无论lazyodd是否为奇数,均更新tr区间奇数个数        return ;    }    else if(y<=w[tr].mid)        update(x,y,z,tr<<1);    else if(x>w[tr].mid)        update(x,y,z,tr<<1|1);    else        update(x,w[tr].mid,z,tr<<1),update(w[tr].mid+1,y,z,tr<<1|1);    w[tr].sum+=(y-x+1)*z;   //更新sum    if(z&1)        w[tr].odd=w[tr<<1].odd+w[tr<<1|1].odd;  //更新线段树中包含(x,y)区间的区间奇数个数}ll query_odd(ll x,ll y,ll tr){    if(w[tr].lazyodd&&w[tr].l!=w[tr].r)  //和update类似    {        w[tr<<1].lazyodd^=1,w[tr<<1|1].lazyodd^=1;        w[tr<<1].odd=w[tr<<1].r-w[tr<<1].l+1-w[tr<<1].odd;        w[tr<<1|1].odd=w[tr<<1|1].r-w[tr<<1|1].l+1-w[tr<<1|1].odd;        w[tr].lazyodd=0;    }    if(w[tr].l==x&&w[tr].r==y)        return w[tr].odd;    else if(w[tr].mid>=y)        return query_odd(x,y,tr<<1);    else if(w[tr].mid<x)        return query_odd(x,y,tr<<1|1);    else        return query_odd(x,w[tr].mid,tr<<1)+query_odd(w[tr].mid+1,y,tr<<1|1);}ll query_sum(ll x,ll y,ll tr){    if(w[tr].lazysum&&w[tr].l!=w[tr].r)  //sum的lazy操作    {        w[tr<<1].lazysum+=w[tr].lazysum;        w[tr<<1|1].lazysum+=w[tr].lazysum;        w[tr<<1].sum+=(w[tr<<1].r-w[tr<<1].l+1)*w[tr].lazysum;        w[tr<<1|1].sum+=(w[tr<<1|1].r-w[tr<<1|1].l+1)*w[tr].lazysum;        w[tr].lazysum=0;    }    if(w[tr].l==x&&w[tr].r==y)        return w[tr].sum;    else if(y<=w[tr].mid)        return query_sum(x,y,tr<<1);    else if(x>w[tr].mid)        return query_sum(x,y,tr<<1|1);    else        return query_sum(x,w[tr].mid,tr<<1)+query_sum(w[tr].mid+1,y,tr<<1|1);}int main(){    ll n,m,i,j,x,z,y;    while(scanf("%lld%lld",&n,&m)!=EOF)    {        char c;        build(1,n,1);        while(m--)        {            scanf("\n%c",&c);            scanf("%lld%lld",&x,&y);            if(c=='S')                printf("%lld\n",query_sum(x,y,1));            else if(c=='Q')                printf("%lld\n",query_odd(x,y,1));            else            {                scanf("%lld",&z);                update(x,y,z,1);            }        }    }    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 墙没有刷乳胶漆怎么办 壁纸不想要了怎么办 自粘墙纸撕不掉怎么办 打雷了怎么办主题画 打雷了怎么办小班教案 费雪小火车不走怎么办 宝宝睡觉要开灯怎么办 门上有人做记号怎么办 颜料粘上衣服洗不掉怎么办 半夜有小偷开锁怎么办 幼儿园人数较多怎么办 附近幼儿园拖班招满了怎么办 6个月大宝宝拉肚子怎么办 婴儿容易吐奶怎么办 新生儿睡眠时间颠倒怎么办 婴儿睡觉黑白颠倒怎么办 婴儿黑白颠倒了怎么办 宝宝肠粘膜受损怎么办 dnf会卡换装怎么办? 孩子不讲理蛮横怎么办 孩子不爱上学了怎么办 幼儿园孩子不爱上学怎么办 额头撞肿了怎么办 两岁半宝宝说话晚怎么办 1岁宝宝拉肚子怎么办? 小孩嗓子老哑怎么办 小孩嗓子经常哑怎么办 小孩子一年级成绩差怎么办 小孩子一年级学习成绩差怎么办 楼上有孩子扰民怎么办 隔壁小孩太吵怎么办 楼上孩子太吵怎么办 泰国贴纸签小孩怎么办 六个月宝宝近视怎么办 孩子视力低应该怎么办 儿童视力低常怎么办 视力储备值低怎么办 六个月宝宝远视怎么办 婴儿喜欢舔衣服怎么办 一岁半宝宝抵抗力差怎么办 两个月宝宝打嗝怎么办