题目链接:http://codeforces.com/contest/438/problem/D
题目大意:
给出一段序列
你需要执行三个操作:
1.求[l,r]的区间和
2.将[l,r]的所有数就对x取余
3.将第k个数赋值为x
题目思路:
其实这个题是队友甩给我的..
首先考虑到一个性质,取余会使得当前x/2
所以考虑到 洛谷开根的 题目
所以只需要维护一个最大值
然后与洛谷的题目一样直接暴力修改即可
复杂度保证可以在nlog2/n,因为每个数最多修改30次
就算有第三个操作,那么也是会增加一个logn的查询或者修改
所以总体复杂度也是:nlogn
Code:
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
typedef long long ll;
using namespace std;
#define rep(i,j,n) for(ll i=j;i<=n;i++)
typedef unsigned long long ull;
const ll INF= 1e16;
const ll maxn = 3e6+7;
const ll mod = 1e9+7;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll num[maxn];
ll mx[maxn];
ll sum[maxn];
void push(int k){
mx[k] = max(mx[k<<1],mx[k<<1|1]);
sum[k] = sum[k<<1] + sum[k<<1|1];
}
void build(int k,int l,int r){
if(l == r){
mx[k] = num[l];
sum[k] = num[l];
return ;
}
int mid = (l+r)/2;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
push(k);
}
void ModifyOne(int k,int l,int r,int pos,ll w){
if(l == r){
mx[k] = w;
sum[k] = w;
return ;
}
int mid = (l+r)/2;
if(pos<=mid) ModifyOne(k<<1,l,mid,pos,w);
else ModifyOne(k<<1|1,mid+1,r,pos,w);
push(k);
}
void Modify(int k,int l,int r,int x,int y,ll w){
if(mx[k]<w) return;
if(l == r){
mx[k] = mx[k]%w;
sum[k] = sum[k]%w;
return;
}
int mid = (l+r)/2;
if(x<=mid) Modify(k<<1,l,mid,x,y,w);
if(y>mid) Modify(k<<1|1,mid+1,r,x,y,w);
push(k);
return;
}
ll Query(int k,int l,int r,int x,int y){
if(x<=l&&y>=r) return sum[k];
int mid = (l+r)/2;
ll ans = 0;
if(x<=mid) ans += Query(k<<1,l,mid,x,y);
if(y>mid) ans += Query(k<<1|1,mid+1,r,x,y);
push(k);
return ans;
}
int main(){
read(n);read(m);
for(int i=1;i<=n;i++) read(num[i]);
build(1,1,n);
for(int i=1;i<=m;i++){
int op,x,y,z;scanf("%d",&op);
if(op == 1){
scanf("%d%d",&x,&y);
printf("%lld\n",Query(1,1,n,x,y));
}else if(op == 2){
scanf("%d%d%d",&x,&y,&z);
Modify(1,1,n,x,y,z);
}else{
scanf("%d%d",&x,&y);
ModifyOne(1,1,n,x,y);
}
}
return 0;
}
/***
***/