poj 3468 线段树 区间内的线段和(成段更新)

来源:互联网 发布:网络棋牌赌博平台出租 编辑:程序博客网 时间:2024/05/16 04:49

题意:基本从题目可以知道了吧~

思路:直接线段树搞TLE,后来看了这个报告

http://hi.baidu.com/lewutian/blog/item/95421b828f63f19df603a6a2.html

知道了,在插入线段的时候不需要一直插到叶子节点,而是用一个“score”来标记某一段区间内的增值。 比如要在 【3 6】 区间插个 3  在找到【 4  5 】 区间的时候就可以把

【4 5】区间节点的“score”的更新成3。哎~看了报告还WA了半天,原来还真有long long 卡你的数据啊。。。悲催。写了这么长的代码,发现对"hh"大牛的线段树模版的仰慕犹如“滔滔江水,连绵不绝”啊。。。那犀利的小位运算和预处理~ 膜拜Orz...一定要拜读~掌握!!!

#include<iostream>using namespace std;struct node{  int lv,rv;  long long score;//这个优化很见效嘛 写成int 看答案也没注意 WA吐血了。。。   long long sum;  int mid()  {    return (lv+rv)/2;  }}e[10000000];long long num[100010];void make_ST(int left,int right,int k){  //printf("%d\n",k);  e[k].lv=left;  e[k].rv=right;  e[k].score=0;  if(left==right)  {    e[k].sum=num[left];    return;  }  int midd=e[k].mid();  make_ST(left,midd,2*k);  make_ST(midd+1,right,2*k+1);  e[k].sum=(e[2*k].sum+e[2*k+1].sum);  return;}void add_ST(int left,int right,int k,long long len){  if(e[k].lv>=left&&e[k].rv<=right)  {    e[k].score+=len;//成段更新 例如更新3--6  找到了[4,5] 就不用往下找了,记录下4-5每一段应该增加的长度     return;  }  else  if(e[k].lv<=left&&right<=e[k].rv) e[k].sum+=((right-left+1)*len);  else if(e[k].lv>=left&&right<=e[k].rv) e[k].sum+=((right-e[k].lv+1)*len);  else if(e[k].lv<=left&&right>=e[k].rv)  e[k].sum+=((e[k].rv-left+1)*len);   int midd=e[k].mid();  if(midd>=left) add_ST(left,right,2*k,len);  if(midd<right) add_ST(left,right,2*k+1,len);  return;}long long sum;void query(int left,int right,int k){  if(e[k].lv>=left&&e[k].rv<=right)  {    sum+=(e[k].sum+e[k].score*(e[k].rv-e[k].lv+1));    return;  }  else  //把这个节点的score信息更新到子节点,因为子节点的score不改变的话,最后求和的时候会出现错误   {    e[2*k].score+=e[k].score;    e[2*k+1].score+=e[k].score;    e[k].sum+=(e[k].score*(e[k].rv-e[k].lv+1));//把增加的数值记录到sum里,score的使命也就完成了,下一步就销毁score     e[k].score=0;//用完就销毁。。。如此残忍。。。   }  int midd=e[k].mid();  if(midd>=left) query(left,right,2*k);  if(midd<right) query(left,right,2*k+1);  return;}int main(){  int N,Q,left,right;  long long len;  char s[2];  while(scanf("%d%d",&N,&Q)!=EOF)  {    for(int i=1;i<=N;i++)    {    scanf("%lld",&num[i]);    //printf("%d\n",num[i]);    }    make_ST(1,N,1);    while(Q--)    {      scanf("%s",s);      if(s[0]=='Q')      {        scanf("%d%d",&left,&right);        sum=0;        query(left,right,1);        printf("%lld\n",sum);      }      else      {        scanf("%d%d%lld",&left,&right,&len);        add_ST(left,right,1,len);      }    }  }  return 0;}

HH版本的

#include<iostream>using namespace std;#define LL long long#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1const int maxn = 100005;LL sum[maxn<<2];LL add[maxn<<2];void PushUP(int rt) {        sum[rt] = sum[rt<<1] + sum[rt<<1|1];        }void PushDown(int rt,int m) {        if (add[rt]) {                //printf("rat=%d\n",rt);                add[rt<<1] += add[rt];                add[rt<<1|1] += add[rt];                sum[rt<<1] += add[rt] * (m - (m >> 1));                sum[rt<<1|1] += add[rt] * (m >> 1);                add[rt] = 0;                }        }void build(int l,int r,int rt) {        add[rt] = 0;        if (l == r) {                scanf("%lld",&sum[rt]);                return ;                }                int m = (l + r) >> 1;        build(lson);        build(rson);        PushUP(rt);}void update(int L,int R,LL len,int l,int r,int rt) {        if (L <= l && R >= r) {                //printf("rt=%d\n",rt);                add[rt] += len;                sum[rt] += (len * (r - l + 1));                return ;                }                       int m = (l + r) >> 1;        PushDown(rt , r - l + 1);        if (m >= L) update(L , R , len , lson);        if (m < R) update(L , R , len , rson);        PushUP(rt); }LL query(int L,int R,int l,int r,int rt) {        if (L <=l && R >= r) {                return sum[rt];                }               int m = (l + r) >> 1;        PushDown(rt , r - l + 1);        LL ret = 0;        if (m >= L) ret += query(L , R , lson);        if (m < R) ret += query(L , R , rson);        return ret; }int main() {        int N,Q;        while (scanf("%d%d",&N,&Q)!=EOF) {                build(1 , N , 1);                char s[4];                int a , b;                LL len;                while (Q --) {                        scanf("%s",s);                        if (s[0] == 'Q') {                                scanf("%d%d",&a,&b);                                printf("%lld\n",query(a , b , 1 , N , 1));                                } else {                                scanf("%d%d%lld",&a,&b,&len);                                update(a , b , len , 1 , N , 1);                                }                }                }        }


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 上海学而思家长陪读听不懂怎么办 高考报名的电话号码填错了怎么办 高考报名用的电话号码变换了怎么办 弟媳妇一个月就大闹一次怎么办 丈夫出轨我亲弟媳妇我怎么办 被山西博大泌尿医院坑了怎么办 家长反应孩子学校受欺负老师怎么办 白色衣服和牛仔裤洗变色了怎么办 生完孩子肚子上的松皮怎么办 xp电脑玩cf进入地图黑屏怎么办 爸妈吵架妈妈走了爸爸哭了该怎么办 总担心旅馆被拍视频传上网怎么办 微博买了猜冠军现在停了怎么办 脸上毛孔大有黑头怎么办小窍门去 进去精神病院出来真的疯了怎么办 房子已过户新业主不交物业费怎么办 村委会欠百姓征地补偿款不给怎么办 因为近亲人人都不看好的婚姻怎么办 碰到工作中特别积极的同事怎么办 丈夫车祸死亡妻子和孩子以后怎么办 丈夫死后妻子改嫁儿子不同意怎么办 满了60岁社保没满15年怎么办 捷豹的dpf灯亮了怎么办 朋友如新直销产品是你该怎么办 传福音接受了却被家人拦阻该怎么办 奶奶出钱由孙子抓奖中奖后怎么办 我不想学车了驾校不同意退学怎么办 2017年大学挂科面临退学怎么办 微信重新登录后东西全没了怎么办 宝宝吃鸡蛋过敏全身起红疹怎么办 180在产蛋鸡因断鸡减产怎么办 住友39熔接机熔接损耗大怎么办 支付宝实名认证刷脸失败怎么办 支付宝注册刷脸不是本人怎么办 小学科学只考88分中学怎么办 收银机关机时才上传数据是怎么办 刚做的系统玩cf卡屏怎么办 办健康证的资料掉了怎么办 刚刚办得的健康证掉了怎么办 房子都过户了银行贷不了款怎么办 我要办大病迁出应该怎么办啊?