CodeForces 438D The Child and Sequence (线段树 暴力)

传送门


题目大意:

  给你一个序列,要求在序列上维护三个操作:

  1)区间求和

  2)区间取模

  3)单点修改

这里的操作二很讨厌,取模必须模到叶子节点上,否则跑出来肯定是错的。没有操作二就是线段树水题了。

既然必须模到叶子节点,那我们就模咯。

 

显然,若$b<c$,则$b%c=b$。

因此我们同时维护一个区间最大值,若某区间内最大值小于模数,就把该分支剪掉。

若$a=b%c$,那么肯定有$a \leq \frac{b}{2}$成立。

也就是说,一个数最多被模$\log_2 x$次。总的时间复杂度为$O(n \log n)$,可以接受(就算取模$log$次以后单点修改将某点的值改大,因为有上述剪枝存在,时间复杂度并不会上升太多)。

代码:

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cctype>
 6 #define foru(i,x,y) for(LL i=x;i<=y;i++)
 7 #define ford(i,x,y) for(LL i=x;i>=y;i--)
 8 #define re(x) x=read()
 9 #define max(a,b) ((aaa=a)>(bbb=b))?aaa:bbb
10 using namespace std;
11 typedef long long LL;
12 typedef double db;
13 const LL inf=1e9;
14 const LL N=2e6+10;
15 
16 struct node{LL s,m;}t[N];
17 LL n,m,aaa,bbb;
18 
19 LL read(){
20     static LL f,x;static char ch;
21     x=f=0;ch=getchar();
22     while(!isdigit(ch)){f=(ch=='-');ch=getchar();}
23     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
24     return f?-x:x;
25 }
26 
27 #define mid ((L+R)>>1)
28 #define ls (k<<1)
29 #define rs ((k<<1)+1)
30 
31 void upd(LL k,LL L,LL R,LL p,LL x){
32     if(p<L||p>R)return;
33     if(L==R){t[k]=(node){x,x};return;}
34     upd(ls,L,mid,p,x);upd(rs,mid+1,R,p,x);
35     t[k].s=t[ls].s+t[rs].s;
36     t[k].m=max(t[ls].m,t[rs].m);
37 }
38 
39 LL qrys(LL k,LL L,LL R,LL l,LL r){
40     if(r<L||l>R)return 0;
41     if(l<=L&&R<=r)return t[k].s;
42     return qrys(ls,L,mid,l,r)+qrys(rs,mid+1,R,l,r);
43 }
44 
45 LL qrym(LL k,LL L,LL R,LL l,LL r){
46     if(r<L||l>R)return 0;
47     if(l<=L&&R<=r)return t[k].m;
48     return max(qrym(ls,L,mid,l,r),qrym(rs,mid+1,R,l,r));
49 }
50 
51 void mo(LL k,LL L,LL R,LL l,LL r,LL x){
52     if(r<L||l>R||t[k].m<x)return;
53     if(L==R){t[k].s%=x;t[k].m=t[k].s;return;}
54     mo(ls,L,mid,l,r,x);mo(rs,mid+1,R,l,r,x);
55     t[k].s=t[ls].s+t[rs].s;
56     t[k].m=max(t[ls].m,t[rs].m);
57 }
58 
59 int main(){
60     LL l,r,x;
61     //freopen("mod.in","r",stdin);freopen("mod.out","w",stdout);
62     re(n);re(m);
63     foru(i,1,n){
64         re(x);
65         upd(1,1,n,i,x);
66     }
67     foru(i,1,m){
68         re(x);re(l);re(r);
69         if(x==1){
70             printf("%I64d\n",qrys(1,1,n,l,r));
71         }else if(x==2){
72             re(x);
73             mo(1,1,n,l,r,x);
74         }else{
75             upd(1,1,n,l,r);
76         }
77     }
78     return 0;
79 }

 

posted @ 2017-10-11 17:21  羊毛羊  阅读(242)  评论(0编辑  收藏  举报