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 }