Codeforces 483D
要求单点修改,区间求和,区间取模
由于一个数只能被取模log次,所以区间取模就变成了单点修改,同时对区间维护一个mx值,如果mx小于模数就不取模
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100000+10;
int setv[maxn*4],mx[maxn*4],n,m,a[maxn];
ll sum[maxn*4];
void pushup(int p)
{
sum[p]=sum[p*2]+sum[p*2+1];
mx[p]=max(mx[p*2],mx[p*2+1]);
}
void pushdown(int p,int l,int r,int mid)
{
if(setv[p])
{
mx[p*2]=mx[p*2+1]=setv[p];
sum[p*2]=(ll)(mid-l+1)*setv[p];
sum[p*2]=(ll)(r-mid)*setv[p];
setv[p*2]=setv[p*2+1]=setv[p];
setv[p]=0;
}
}
void build(int p,int l,int r)
{
if(l==r)
{
sum[p]=mx[p]=a[l];
return;
}
int mid=(l+r)>>1;
build(p*2,l,mid);build(p*2+1,mid+1,r);
pushup(p);
}
ll query(int p,int l,int r,int x,int y)
{
if(x>r||y<l) return 0;
if(l>=x&&r<=y) return sum[p];
int mid=(l+r)>>1;pushdown(p,l,r,mid);
return query(p*2,l,mid,x,y)+query(p*2+1,mid+1,r,x,y);
}
void update(int p,int l,int r,int x,int y,int v)
{
if(x>r||y<l||mx[p]<v) return;
if(l==r)
{
sum[p]=mx[p]=mx[p]%v;
return;
}
int mid=(l+r)>>1;pushdown(p,l,r,mid);
update(p*2,l,mid,x,y,v);update(p*2+1,mid+1,r,x,y,v);
pushup(p);
}
void update2(int p,int l,int r,int x,int y,int v)
{
if(x>r||y<l) return;
if(l>=x&&r<=y)
{
mx[p]=setv[p]=v;
sum[p]=(ll)(r-l+1)*v;
return;
}
int mid=(l+r)>>1;
pushdown(p,l,r,mid);
update2(p*2,l,mid,x,y,v);update2(p*2+1,mid+1,r,x,y,v);
pushup(p);
}
int main()
{
//freopen("test.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int op,l,r,k,x;scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&l,&r);
printf("%I64d\n",query(1,1,n,l,r));
}
if(op==2)
{
scanf("%d%d%d",&l,&r,&x);
update(1,1,n,l,r,x);
}
if(op==3)
{
scanf("%d%d",&k,&x);
update2(1,1,n,k,k,x);
}
}
return 0;
}
UOJ228
支持区间开根,区间加,区间求和
由于开根很容易使得一段数都相同,所以区间开根就变成了区间加
剪枝条件为mx==mn||mx-mn==1&&sqrt(mx)!=sqrt(mn)
感觉前半部分很好想,但后半部分就有点难了,不过某次多校只要mx==mn就可以现场AC
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100000+10;
const double eps=1e-12;
int n,m,a[maxn];
ll sum[maxn*4],add[maxn*4],mx[maxn*4],mn[maxn*4];
void pushup(int p)
{
sum[p]=sum[p*2]+sum[p*2+1];
mx[p]=max(mx[p*2],mx[p*2+1]);
mn[p]=min(mn[p*2],mn[p*2+1]);
}
void pushdown(int p,int l,int r,int mid)
{
if(add[p])
{
mx[p*2]+=add[p];mx[p*2+1]+=add[p];
mn[p*2]+=add[p];mn[p*2+1]+=add[p];
sum[p*2]+=(ll)(mid-l+1)*add[p];
sum[p*2+1]+=(ll)(r-mid)*add[p];
add[p*2]+=add[p];add[p*2+1]+=add[p];
add[p]=0;
}
}
void build(int p,int l,int r)
{
if(l==r)
{
sum[p]=mx[p]=mn[p]=a[l];
return;
}
int mid=(l+r)>>1;
build(p*2,l,mid);build(p*2+1,mid+1,r);
pushup(p);
}
ll query(int p,int l,int r,int x,int y)
{
if(x>r||y<l) return 0;
if(l>=x&&r<=y) return sum[p];
int mid=(l+r)>>1;
pushdown(p,l,r,mid);
return query(p*2,l,mid,x,y)+query(p*2+1,mid+1,r,x,y);
}
void update(int p,int l,int r,int x,int y,int v)
{
if(x>r||y<l) return;
if(l>=x&&r<=y)
{
sum[p]+=(ll)(r-l+1)*v;mn[p]+=v;mx[p]+=v;
add[p]+=v;
return;
}
int mid=(l+r)>>1;
pushdown(p,l,r,mid);
update(p*2,l,mid,x,y,v);update(p*2+1,mid+1,r,x,y,v);
pushup(p);
}
void update2(int p,int l,int r,int x,int y)
{
if(x>r||y<l) return;
if(l>=x&&r<=y)
{
if(mx[p]==mn[p]||(mx[p]-mn[p]==1&&(int)sqrt(mx[p])!=(int)sqrt(mn[p])))
{
ll val=mx[p]-(int)sqrt(mx[p]);
mx[p]-=val;mn[p]-=val;sum[p]-=(ll)(r-l+1)*val;
add[p]-=val;
return;
}
}
int mid=(l+r)>>1;
pushdown(p,l,r,mid);
update2(p*2,l,mid,x,y);update2(p*2+1,mid+1,r,x,y);
pushup(p);
}
int main()
{
//freopen("test.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int op,l,r,k,x;scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&l,&r,&x);
update(1,1,n,l,r,x);
}
if(op==2)
{
scanf("%d%d",&l,&r);
update2(1,1,n,l,r);
}
if(op==3)
{
scanf("%d%d",&l,&r);
printf("%lld\n",query(1,1,n,l,r));
}
}
return 0;
}