The Child and Sequence

Codeforces Round #250 (Div. 1)D:http://codeforces.com/problemset/problem/438/D

题意:给你一个序列,然后有3种操作 1x y.表示查询[x,y]之间的区间和,2 x y z表示把[x y]内的数%z,3x y,表示把第x个数变成y。

题解:肯定是用线段树来维护,但是一开始想不到维护什么统计量,对于区间取模,没办法用lazy标记,更新到第的话,肯定会T。后来,认为既然没办法用lazy,那么只能用别的方法来优化更新。发现每次取模之后,数都会变小,如果要取模的数比当前模数小的话,就不用取模,于是可以维护区间最大值,如果区间最大值都小于模数的话,这个区间肯定不用更新,这样来减少更新。这样的方法,其实以前也做过,就是对于一个区间内的数进行开平方操作,每个数会越开越小,到了1的时候就可以直接不开了。因此,对于线段树的区间更新来说:1如果能找到好的lazy可以标记的话,就使用lazy标记;2如果找不到就要想办法优化区间更新,让单点更新的次数变少。另外此题,自己用线段树省空间的写法,结果不熟练,一个地方写错,最后wa几发。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int N=1e5+19;
 7 int n,m;
 8 long long sum[N*4],maxn[N*4];
 9 void pushup(int rt){
10    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
11    maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
12 }
13 void build(int l,int r,int rt){
14     if(l==r){
15         scanf("%I64d",&maxn[rt]);
16         sum[rt]=maxn[rt];
17         return;
18     }
19     int mid=(l+r)/2;
20     build(l,mid,rt<<1);
21     build(mid+1,r,rt<<1|1);
22     pushup(rt);
23 }
24 void update(int l,int r,int rt,int from,int to,long long mod){
25      if(maxn[rt]<mod)return;
26      if(l==r){
27         maxn[rt]%=mod;
28         sum[rt]=maxn[rt];
29         return;
30      }
31      int mid=(l+r)/2;
32     if(mid>=to)update(l,mid,rt<<1,from,to,mod);
33     else if(mid<from)update(mid+1,r,rt<<1|1,from,to,mod);
34     else{
35         update(l,mid,rt<<1,from,mid,mod);
36         update(mid+1,r,rt<<1|1,mid+1,to,mod);
37     }
38   pushup(rt);
39 }
40 void update2(int l,int r,int rt,int pos,long long val){
41      if(l==r){
42         maxn[rt]=val;
43         sum[rt]=val;
44         return;
45      }
46      int mid=(l+r)/2;
47     if(mid>=pos)update2(l,mid,rt<<1,pos,val);
48     else update2(mid+1,r,rt<<1|1,pos,val);
49   pushup(rt);
50 }
51 long long query(int l,int r,int rt,int from,int to){
52     if(l==from&&r==to){
53         return sum[rt];
54     }
55    int mid=(l+r)/2;
56    if(mid>=to)return query(l,mid,rt<<1,from,to);
57    else if(mid<from)return query(mid+1,r,rt<<1|1,from,to);
58    else {
59       return query(l,mid,rt<<1,from,mid)+query(mid+1,r,rt<<1|1,mid+1,to);
60 
61    }
62 }
63 int t,t1,t4;
64 long long t2,t3;
65 int main(){
66   while(~scanf("%d%d",&n,&m)){
67       memset(sum,0,sizeof(sum));
68       memset(maxn,0,sizeof(maxn));
69       build(1,n,1);
70       for(int i=1;i<=m;i++){
71         scanf("%d%d",&t,&t1);
72         if(t==1){
73             scanf("%d",&t4);
74             printf("%I64d\n",query(1,n,1,t1,t4));
75       }
76       else if(t==2){
77         scanf("%d%I64d",&t4,&t2);
78          update(1,n,1,t1,t4,t2);
79       }
80       else{
81             scanf("%I64d",&t2);
82         update2(1,n,1,t1,t2);
83       }
84     }
85   }
86 }
View Code

 

posted on 2014-07-26 14:20  天依蓝  阅读(297)  评论(0编辑  收藏  举报

导航