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

 

posted @ 2013-07-11 19:50  ihge2k  阅读(732)  评论(0编辑  收藏  举报