hihoCoder #1078 : 线段树的区间修改

 

G++ 213ms 12MB

 

题意:给一个序列,询问时要返回给定区间的和,修改时整个区间都改成一个值。

思路:

  按提示说的做。线段树,再设置lazy_tag,必要时再修改

  查询时遇到tag就将自身分配成两半分别给左右孩子(如果有的话),然后为左右孩子置tag,取消自身的tag。当查询的节点刚好有tag,不用管了(用不到其孩子),直接返回即可。

  修改时遇到tag按照查询的那种方法,用不到孩子就不用改,用到的时候必须将tag往下推给孩子。注意此题是要返回区间和,所以如果答案有多个区间的,必须return多个区间的和。

 

 1 #include <bits/stdc++.h>

 2 using namespace std;

 3 const int N=100010;

 4 int n, q, op, l, r, flag, sma;

 5 int w[N];

 6 int ans[N];

 7 

 8 void cal(int t)//从t开始计算,ans[i]表示1~i的和

 9 {

10     for(int i=t; i<=n; i++)

11         ans[i]=ans[i-1]+w[i];

12 }

13 

14 int main()

15 {

16     //freopen("input.txt", "r", stdin);

17     sma=0x7fffffff;

18     cin>>n;

19     for(int i=0; i<n; i++)    scanf("%d",&w[i+1]);

20     cin>>q;

21     cal(1);//先算一次

22     for(int i=0; i<q; i++)

23     {

24         scanf("%d",&op);

25         int a,b,c;

26         if(op)  //修改

27         {

28             scanf("%d%d%d",&a,&b,&c);

29             for(int i=a; i<=b; i++)    w[i]=c;

30             if(a<sma)

31                 sma=a;//需要修改的地方sma~n。若多次修改,只需要一次从最小的sma开始修改

32             flag=a;//需要修改的标志

33         }

34         else    //查询

35         {

36             if(flag)

37             {

38                 cal(sma);

39                 sma=0x7fffffff;

40                 flag=0;

41             }

42             scanf("%d%d", &a,&b);

43             printf("%d\n",ans[b]-ans[a-1]);

44         }

45     }

46     return 0;

47 }
偷懒的TLE代码

 

  1 #include <bits/stdc++.h>

  2 using namespace std;

  3 const int N=100010;

  4 int n, q, L, R, op, a, b, W;

  5 struct node

  6 {

  7     int v;

  8     bool flag;

  9     node *ll,*rr;

 10 

 11 };

 12 

 13 node* create()  //创建节点

 14 {

 15     node *tmp=new(node);

 16     tmp->flag=tmp->v=0;

 17     tmp->ll=tmp->rr=0;

 18     return tmp;

 19 }

 20 

 21 node* init_tree(int l,int r)    //初始化树

 22 {

 23     node *tmp=create();

 24     if(l==r)

 25     {

 26         scanf("%d",&tmp->v);

 27         return tmp;

 28     }

 29     tmp->ll=init_tree(l,(r+l)>>1);

 30     tmp->rr=init_tree(((r+l)>>1)+1,r);

 31     tmp->v =tmp->ll->v + tmp->rr->v;

 32     return tmp;

 33 }

 34 

 35 int query(int l,int r,int LL,int RR,node *t) //查询(欲查询的左,右,区间下限,上限,根)

 36 {

 37     if(l==LL&&r==RR)    return t->v;

 38     int mid=((RR+LL)>>1);

 39     if(t->flag)

 40     {

 41         if(t->ll)

 42         {

 43             t->ll->flag=t->rr->flag=1;

 44             t->rr->v=t->v/(RR-LL+1)*(RR-mid);

 45             t->ll->v=t->v-t->rr->v;

 46         }

 47         t->flag=0;

 48     }

 49     if(l>mid)    return query(l,r,mid+1,RR,t->rr);

 50     if(r<=mid)    return query(l,r,LL,mid,t->ll);

 51     return query(l,mid,LL,mid,t->ll)+query(mid+1,r,mid+1,RR,t->rr);

 52 }

 53 void update(int l,int r,int LL,int RR,node *t)   //修改。

 54 {

 55     if(l==LL&&r==RR)

 56     {

 57         t->flag=1;

 58         t->v=(r-l+1)*W;

 59         //cout<<"****"<<t->v<<endl;

 60         return ;

 61     }

 62     //修改的过程中也可能遇到flag=1的情况,要进行改;

 63     int mid=((LL+RR)>>1);

 64     if(t->flag)

 65     {

 66         if(t->ll)

 67         {

 68             t->rr->flag=t->ll->flag=1;

 69             t->rr->v= t->v/(RR-LL+1)*(RR-mid);

 70             t->ll->v= t->v - t->rr->v;

 71         }

 72         t->flag=0;

 73     }

 74     if(l>mid)    update(l, r, mid+1, RR, t->rr);  //要改的在右边

 75     else if(r<=mid)    update(l, r, LL, mid, t->ll);

 76     else

 77     {

 78         update(l, mid, LL, mid, t->ll);

 79         update(mid+1, r, mid+1, RR, t->rr);

 80     }

 81     t->v= t->ll->v + t->rr->v;

 82 }

 83 int main()

 84 {

 85     //freopen("input.txt", "r", stdin);

 86     cin>>n;

 87     node *tree=init_tree(1,n);

 88     //cout<<query(2,n,1,n,tree)<<endl;

 89     cin>>q;

 90     for(int i=0; i<q; i++)

 91     {

 92         scanf("%d",&op);

 93         if(op)  //修改

 94         {

 95             scanf("%d%d%d",&a,&b,&W);

 96             update(a,b,1,n,tree);

 97         }

 98         else    //查询

 99         {

100             scanf("%d%d",&L,&R);

101             printf("%d\n",query(L,R,1,n,tree) );

102         }

103     }

104     return 0;

105 }
AC代码

 

你可能感兴趣的:(code)