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\n",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

 

你可能感兴趣的:(lazy)