题目:http://codeforces.com/problemset/problem/438/D 

一个数取模n%m,有两种情况、

1.m>n, n%m=n;

2.m<=n, n%m<=n/2;

所以当m>n时,取模操作可以忽略。

每个a[i]最多需要log(a[i])次取模操作变为0,因此我们可以对所有取模进行暴力更新。最多要更新n*log(a[i])次,由于单次更新复杂度为log(n),所以总复杂度为n*logn*log(a[i]).

#include <bits/stdc++.h>

using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=111111;
int col[maxn<<2];
long long sum[maxn<<2],Max[maxn<<2];
int n,m;
void pushup(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void build(int l,int r,int rt){
    if(l==r){
        cin>>sum[rt];
        Max[rt]=sum[rt];
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
int op,l,r,x;
void setvalue(int pos,int val,int l,int r,int rt){
    if(l==r){
        sum[rt]=Max[rt]=val;
        return;
    }
    int m=(l+r)>>1;
    if(pos<=m)setvalue(pos,val,lson);
    else setvalue(pos,val,rson);
    pushup(rt);
}
void update(int L,int R,int val,int l,int r,int rt){
    if(l==r){
        sum[rt]%=val;
        Max[rt]=sum[rt];
        return;
    }
    int m=(l+r)>>1;
    if(L<=m&&Max[rt<<1]>=val)update(L,R,val,lson);
    if(R>m&&Max[rt<<1|1]>=val)update(L,R,val,rson);
    pushup(rt);
}
long long query(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r)return sum[rt];
    long long ans=0;
    int m=(l+r)>>1;
    if(L<=m)ans+=query(L,R,lson);
    if(R>m)ans+=query(L,R,rson);
    return ans;
}
int main()
{
//    freopen("in","r",stdin);
    while(cin>>n>>m){
        build(1,n,1);
        while(m--){
            scanf("%d",&op);
            if(op==3){
                scanf("%d%d",&l,&x);
                setvalue(l,x,1,n,1);
            }
            else if(op==2){
                scanf("%d%d%d",&l,&r,&x);
                update(l,r,x,1,n,1);
            }
            else {
                scanf("%d%d",&l,&r);
                printf("%I64d\n",query(l,r,1,n,1));
            }
        }
    }
    return 0;
}