• poj 3468(线段树+lazy思想)


    题目链接:http://poj.org/problem?id=3468

    思路:如果直接去做,每次都更新到叶子节点,那必然会TLE,我们可以采用lazy的思想:没必要每次更新都更新到叶子节点,只要有一个合适的范围就用一个增量来记录它,当下一次询问时,如果这个范围正好合适询问的范围,就直接是这个节点的sum值加上这个区间长度*lnc,再加到总和上去,若这个节点的范围不适合所要查询的范围,那么就要查询它的子节点,这个时候再把增量传给她的子节点,并且清空父亲节点的增量,这样效率能大大提高。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 #define MAXN 100010
      7 typedef long long ll;
      8 
      9 struct Node{
     10     int L,R;
     11     ll lnc;//增量
     12     ll sum;
     13 }node[MAXN<<2];
     14 
     15 int N,Q;
     16 
     17 void Build(int L,int R,int rt)
     18 {
     19     if(L==R){
     20         node[rt].lnc=node[rt].sum=0;
     21         return ;
     22     }
     23     node[rt].lnc=node[rt].sum=0;
     24     int M=(L+R)>>1;
     25     Build(L,M,rt<<1);
     26     Build(M+1,R,(rt<<1)|1);
     27 }
     28 
     29 void Updata(int L,int R,int rt,int id,ll x)
     30 {
     31     if(L==id&&R==id){
     32         node[rt].sum=x;
     33         return ;
     34     }
     35     node[rt].sum+=x;
     36     int M=(L+R)>>1;
     37     if(id<=M){
     38         Updata(L,M,rt<<1,id,x);
     39     }else 
     40         Updata(M+1,R,(rt<<1)|1,id,x);
     41 }
     42 
     43 void Add_Updata(int L,int R,int rt,int l,int r,ll x)
     44 {
     45     if(l<=L&&R<=r){
     46         node[rt].lnc+=x;//若此节点所在区段被包含在要插入的区段中,就将插入值存在lnc中,return;
     47         return ;
     48     }else if(L<=l&&r<=R){
     49         node[rt].sum+=(r-l+1)*x;
     50     }else if(L>=l&&R>=r){
     51         node[rt].sum+=(r-L+1)*x;
     52     }else if(L<=l&&R<=r){
     53         node[rt].sum+=(R-l+1)*x;
     54     }
     55     int M=(L+R)>>1;
     56     if(r<=M){
     57         Add_Updata(L,M,rt<<1,l,r,x);
     58     }else if(l>M){
     59         Add_Updata(M+1,R,(rt<<1)|1,l,r,x);
     60     }else {
     61         Add_Updata(L,M,rt<<1,l,r,x);
     62         Add_Updata(M+1,R,(rt<<1)|1,l,r,x);
     63     }
     64 }
     65 
     66 ll sum;
     67 void Query(int L,int R,int rt,int l,int r)
     68 {
     69     if(l<=L&&R<=r){
     70         sum+=node[rt].sum+node[rt].lnc*(R-L+1);
     71         return ;
     72     }
     73     //若上面if条件不成立,则要询问它的子节点,此时增量要下传,并且要更新其本身的sum;
     74     node[rt<<1].lnc+=node[rt].lnc;
     75     node[(rt<<1)|1].lnc+=node[rt].lnc;
     76     node[rt].sum+=node[rt].lnc*(R-L+1);
     77     node[rt].lnc=0;
     78     int M=(L+R)>>1;
     79     if(r<=M){
     80         Query(L,M,rt<<1,l,r);
     81     }else if(l>M){
     82         Query(M+1,R,(rt<<1)|1,l,r);
     83     }else {
     84         Query(L,M,rt<<1,l,r);
     85         Query(M+1,R,(rt<<1)|1,l,r);
     86     }
     87 }
     88 
     89 int main()
     90 {
     91     int a,b,c;
     92     char str[11];
     93     scanf("%d%d",&N,&Q);
     94     Build(1,N,1);
     95     for(int i=1;i<=N;i++){
     96         scanf("%d",&a);
     97         Updata(1,N,1,i,(ll)a);
     98     }
     99     while(Q--){
    100         scanf("%s",str);
    101         if(str[0]=='Q'){
    102             scanf("%d%d",&a,&b);
    103             sum=0;
    104             Query(1,N,1,a,b);
    105             printf("%lld
    ",sum);
    106         }else {
    107             scanf("%d%d%d",&a,&b,&c);
    108             Add_Updata(1,N,1,a,b,(ll)c);
    109         }
    110     }
    111     return 0;
    112 }
    113  
    114 
    115     
    View Code
  • 相关阅读:
    PCM存储格式 Intel 和 Motorola
    shell 命令行
    机器学习 | 算法笔记- 集成学习(Ensemble Learning)
    基于深度学习的目标检测综述
    机器学习 | 算法笔记- 逻辑斯蒂回归(Logistic Regression)
    机器学习 | 算法笔记- 朴素贝叶斯(Naive Bayesian)
    机器学习 | 算法笔记- 支持向量机(Support Vector Machine)
    机器学习 | 算法笔记- k近邻(KNN)
    机器学习 | 算法笔记- 决策树(Decision Tree)
    机器学习 | 算法笔记- 线性回归(Linear Regression)
  • 原文地址:https://www.cnblogs.com/wally/p/3184918.html
Copyright © 2020-2023  润新知