先呈上原题链接[Codeforces Round #250 (Div. 1) D. The Child and Sequence]
题意:
给定一组数有三个操作:
区间每个值对
P
P
P 求模;
单点修改
询问区间和
思路:
两棵线段树,一个维护区间最大值,一个维护区间和。
因为求模运算每次至少是折半的,所以对需要求模的暴力修改就行了。
坑点:
无
good luck and have fun!!!
附上代码:
#include<bits/stdc++.h>
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define test(flag,value) cout<<flag<<":"<<(value)<<endl
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const int MAXN=1e6+5;
const double PI=acos(-1);
LL maxx[MAXN],sum[MAXN];
int a[MAXN];
inline void push_up(int rt)
{
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r, int rt)
{
if(l==r){
maxx[rt]=sum[rt]=1ll*a[l];
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
push_up(rt);
}
void update(int L,int R,int l,int r,int rt,int p)
{
if(maxx[rt]<p)
return;
if(l==r)
{
maxx[rt]%=p;
sum[rt]%=p;
return ;
}
int m=(l+r)>>1;
if(m>=L) update(L,R,l,m,rt<<1,p);
if(m<R) update(L,R,m+1,r,rt<<1|1,p);
push_up(rt);
}
void update2(int pos,int l,int r,int rt,int val)
{
if(l==r&&l==pos)
{
sum[rt]=val;
maxx[rt]=val;
return;
}
int m=(l+r)>>1;
if(m>=pos) update2(pos,l,m,rt<<1,val);
if(m<pos) update2(pos,m+1,r,rt<<1|1,val);
push_up(rt);
}
LL query(int L,int R,int l, int r,int rt)
{
if(L<=l&&r<=R) return sum[rt];
int m=(l+r)>>1;
LL res=0;
if(m>=L) res+=query(L,R,l,m,rt<<1);
if(m<R) res+=query(L,R,m+1,r,rt<<1|1);
return res;
}
int main(void)
{
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
build(1,n,1);
while(m--)
{
int type;scanf("%d",&type);
if(type==1)
{
int l,r;scanf("%d%d",&l,&r);
printf("%lld\n", query(l,r,1,n,1));
}
else if(type==2)
{
int l,r,x;scanf("%d%d%d",&l,&r,&x);
update(l,r,1,n,1,x);
}
else if(type==3)
{
int k,x;scanf("%d%d",&k,&x);
update2(k,1,n,1,x);
}
}
}