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