sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧。
在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手。于是她的好朋友九条可怜酱给她出了一道题。
给出一个长度为 nn 的数列 AA,接下来有 mm 次操作,操作有三种:
- 对于所有的 i∈[l,r]i∈[l,r],将 AiAi 变成 Ai+xAi+x。
- 对于所有的 i∈[l,r]i∈[l,r],将 AiAi 变成 ⌊Ai−−√⌋⌊Ai⌋。
- 对于所有的 i∈[l,r]i∈[l,r],询问 AiAi 的和。
作为一个不怎么熟练的初学者,sylvia 想了好久都没做出来。而可怜酱又外出旅游去了,一时间联系不上。于是她决定向你寻求帮助:你能帮她解决这个问题吗。
输入格式
第一行两个数:n,mn,m。
接下来一行 nn 个数 AiAi。
接下来 mm 行中,第 ii 行第一个数 titi 表示操作类型:
若 ti=1ti=1,则接下来三个整数 li,ri,xili,ri,xi,表示操作一。
若 ti=2ti=2,则接下来三个整数 li,rili,ri,表示操作二。
若 ti=3ti=3,则接下来三个整数 li,rili,ri,表示操作三。
输出格式
对于每个询问操作,输出一行表示答案。
样例一
input
5 5 1 2 3 4 5 1 3 5 2 2 1 4 3 2 4 2 3 5 3 1 5
output
5 6
题解: 其实这个题是随便写的,举个栗子 100 20-->10 4--->3 2----> 1 1,所以我们可以猜个结论,就是在我们可以接受次的开根号这个序列趋于相同
要是这个区间的差大于1我们就暴力dfs修改,我们可以感性的知道肯定不会修改很多次,对于这个区间: 如果 maxn-minn==0,就相当于区间覆盖,
对于3 4,开根号后变成了1 2,他们的 maxn-minn还是等于1,这样子相当于一个区间加减,然后总之就是一个双标记的问题。
hint: 应该在putdown的时候更新左右孩子的信息。
#include<bits/stdc++.h>
using namespace std;
const int N=100000*5;
long long setv[N],maxv[N],minv[N],addv[N],a[N],sumv[N];
long long _max,_min,_sum;
long long n,m;
long long w;
void build(long long o,long long l,long long r)
{
if(l==r)
{
sumv[o]=maxv[o]=minv[o]=a[l];
return;
}
long long mid=(r+l)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
sumv[o]=sumv[o*2+1]+sumv[o*2];
maxv[o]=max(maxv[o*2],maxv[o*2+1]);
minv[o]=min(minv[o*2],minv[o*2+1]);
}
void query(long long o,long long l,long long r,long long ql,long long qr,long long add)
{
if(setv[o]>0)
{
_sum+=(setv[o]+add)*(long long)(min(qr,r)-max(ql,l)+1);
}
else if(ql<=l&&qr>=r)
{
_sum+=sumv[o]+(add)*(long long)(r-l+1);
}
else
{
int mid=(l+r)/2;
if(ql<=mid) query(o*2,l,mid,ql,qr,add+addv[o]);
if(qr>mid) query(o*2+1,mid+1,r,ql,qr,add+addv[o]);
}
}
void maintain(int o,int l,int r)
{
int lc=o*2,rc=o*2+1;
if(setv[o]!=0)
{
sumv[o]=setv[o]*(r-l+1);
maxv[o]=setv[o]; minv[o]=setv[o];
}
else
{
if(r>l){
sumv[o]=sumv[rc]+sumv[lc]+addv[o]*(r-l+1);
maxv[o]=max(maxv[rc],maxv[lc])+addv[o];
minv[o]=min(minv[rc],minv[lc])+addv[o];}
}
}
void Puttage(int o,int l,int r)
{
int mid=(l+r)/2;
int lc=o*2,rc=o*2+1;
if(r>l){
int lc=o*2,rc=o*2+1;
if(setv[o]!=0)
{
setv[o*2]=setv[o]; setv[o*2+1]=setv[o];
addv[rc]=addv[lc]=0;
sumv[lc]=setv[lc]*(mid-l+1);
maxv[lc]=setv[lc]; minv[lc]=setv[lc];
sumv[rc]=setv[rc]*(r-mid);
maxv[rc]=setv[rc]; minv[rc]=setv[rc];
setv[o]=0;
}
else
{
if(setv[rc]!=0) {setv[rc]+=addv[o]; sumv[rc]=setv[rc]*(r-mid); maxv[rc]=setv[rc]; minv[rc]=setv[rc];}
else {addv[rc]+=addv[o]; sumv[rc]=sumv[rc]+addv[o]*(r-mid); maxv[rc]=maxv[rc]+addv[o]; minv[rc]=minv[rc]+addv[o];}
if(setv[lc]!=0) {setv[lc]+=addv[o]; sumv[lc]=setv[lc]*(mid-l+1); maxv[lc]=setv[lc]; minv[lc]=setv[lc];}
else {addv[lc]+=addv[o]; sumv[lc]=sumv[lc]+addv[lc]*(l-mid+1); maxv[lc]=maxv[lc]+addv[o]; minv[lc]=minv[lc]+addv[o];}
addv[o]=0;
}}
}
void change(int x,int l,int r,int ql,int qr,int k)
{
if(ql>r||qr<l) return;
if(ql<=l&&qr>=r)
{
if(l==r)
{
if(setv[x]==0) a[l]+=addv[x];
else a[l]=setv[x];
setv[x]=addv[x]=0;
if(k==1)
{
a[l]+=w;
sumv[x]=a[l];
maxv[x]=a[l]; minv[x]=a[l];
return;
}
else
{
a[l]=(int)sqrt(a[l]);
sumv[x]=a[l];
maxv[x]=a[l]; minv[x]=a[l];
return;
}
}
if(k==1)
{
if(setv[x]>0)
{
setv[x]+=w;
maintain(x,l,r);
return;
}
else
{
addv[x]+=w;
maintain(x,l,r);
return;
}
}
else
{
_max=maxv[x]; _min=minv[x];
if(_max==_min)
{
int temp=(int)sqrt(_min);
setv[x]=temp;
if(addv[x]!=0) addv[x]=0;
maintain(x,l,r);
return;
}
else
{
if(_max-_min==1)
{
int temp=(int)sqrt(_max);
int temp2=(int)sqrt(_min);
if(temp-temp2==1)
{
addv[x]-=_max-temp;
maintain(x,l,r);
return;
}
else if(temp-temp2==0)
{
setv[x]=temp;
if(addv[x]!=0) addv[x]=0;
maintain(x,l,r);
return;
}
else
{
Puttage(x,l,r);
int mid=(r+l)/2;
maintain(x*2,l,mid);
maintain(x*2+1,mid+1,r);
}
}
else
{
Puttage(x,l,r);
int mid=(r+l)/2;
maintain(x*2,l,mid);
maintain(x*2+1,mid+1,r);
}
}
}
}
else
{
Puttage(x,l,r);
int mid=(r+l)/2;
maintain(x*2,l,mid);
maintain(x*2+1,mid+1,r);
}
int mid=(r+l)/2;
change(x*2,l,mid,ql,qr,k);
change(x*2+1,mid+1,r,ql,qr,k);
maintain(x,l,r);
}
int main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int t;
int ql,qr;
scanf("%d",&t);
if(t==1)
{
scanf("%d%d%lld",&ql,&qr,&w);
change(1,1,n,ql,qr,1);
}
else if(t==2)
{
scanf("%d%d",&ql,&qr);
change(1,1,n,ql,qr,2);
}
else
{
_sum=0;
scanf("%d%d",&ql,&qr);
query(1,1,n,ql,qr,0);
printf("%lld
",_sum);
}
}
// return 0;
}
//3802450110