题面:http://uoj.ac/problem/228
正解:线段树。
我们可以发现,开根号时一个区间中的数总是趋近相等。判断一个区间的数是否相等,只要判断最大值和最小值是否相等就行了。如果这个区间的数相等,那么他们开方的数也相等,我们直接转化为减去一个数就行了。
但是这是没有办法$AC$的,我们还要加一个特判,就是最大值与最小值差为$1$,且他们开方以后的差也为$1$,如$8$和$9$这两个数,这样就能通过所有数据了。复杂度证明?我不会。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define ls (x<<1) 15 #define rs (x<<1|1) 16 #define N (100010) 17 #define il inline 18 #define RG register 19 #define ll long long 20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 21 22 using namespace std; 23 24 ll lazy[4*N],sum[4*N],mx[4*N],mn[4*N],a[N],n,m; 25 26 il ll gi(){ 27 RG ll x=0,q=1; RG char ch=getchar(); 28 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 29 if (ch=='-') q=-1,ch=getchar(); 30 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 31 return q*x; 32 } 33 34 il void add(RG ll x,RG ll l,RG ll r,RG ll v){ 35 sum[x]+=(r-l+1)*v,mx[x]+=v,mn[x]+=v,lazy[x]+=v; return; 36 } 37 38 il void merge(RG ll x,RG ll l,RG ll r){ 39 sum[x]=sum[ls]+sum[rs]+(r-l+1)*lazy[x]; 40 mx[x]=max(mx[ls],mx[rs])+lazy[x]; 41 mn[x]=min(mn[ls],mn[rs])+lazy[x]; 42 return; 43 } 44 45 il void build(RG ll x,RG ll l,RG ll r){ 46 if (l==r){ sum[x]=mx[x]=mn[x]=a[l]; return; } 47 RG ll mid=(l+r)>>1; 48 build(ls,l,mid),build(rs,mid+1,r); 49 merge(x,l,r); return; 50 } 51 52 il void update(RG ll x,RG ll l,RG ll r,RG ll xl,RG ll xr,RG ll v){ 53 if (xl<=l && r<=xr){ add(x,l,r,v); return; } RG ll mid=(l+r)>>1; 54 if (xr<=mid) update(ls,l,mid,xl,xr,v); 55 else if (xl>mid) update(rs,mid+1,r,xl,xr,v); 56 else update(ls,l,mid,xl,mid,v),update(rs,mid+1,r,mid+1,xr,v); 57 merge(x,l,r); return; 58 } 59 60 il void Sqrt(RG ll x,RG ll l,RG ll r,RG ll xl,RG ll xr,RG ll la){ 61 if (xl<=l && r<=xr){ 62 if (mn[x]==mx[x]){ 63 RG ll del=mx[x]+la-(ll)sqrt(mx[x]+la); 64 add(x,l,r,-del); return; 65 } else{ 66 RG ll s1=(ll)sqrt(mn[x]+la),s2=(ll)sqrt(mx[x]+la); 67 if (mn[x]+1==mx[x] && s1+1==s2){ 68 RG ll del=mx[x]+la-s2; 69 add(x,l,r,-del); return; 70 } 71 } 72 } 73 RG ll mid=(l+r)>>1; la+=lazy[x]; 74 if (xr<=mid) Sqrt(ls,l,mid,xl,xr,la); 75 else if (xl>mid) Sqrt(rs,mid+1,r,xl,xr,la); 76 else Sqrt(ls,l,mid,xl,mid,la),Sqrt(rs,mid+1,r,mid+1,xr,la); 77 merge(x,l,r); return; 78 } 79 80 il ll query(RG ll x,RG ll l,RG ll r,RG ll xl,RG ll xr,RG ll la){ 81 if (xl<=l && r<=xr) return sum[x]+(r-l+1)*la; 82 RG ll mid=(l+r)>>1; la+=lazy[x]; 83 if (xr<=mid) return query(ls,l,mid,xl,xr,la); 84 else if (xl>mid) return query(rs,mid+1,r,xl,xr,la); 85 else return query(ls,l,mid,xl,mid,la)+query(rs,mid+1,r,mid+1,xr,la); 86 } 87 88 il void work(){ 89 n=gi(),m=gi(); for (RG ll i=1;i<=n;++i) a[i]=gi(); build(1,1,n); 90 for (RG ll i=1,type,l,r,x;i<=m;++i){ 91 type=gi(); 92 if (type==1) l=gi(),r=gi(),x=gi(),update(1,1,n,l,r,x); 93 if (type==2) l=gi(),r=gi(),Sqrt(1,1,n,l,r,0); 94 if (type==3) l=gi(),r=gi(),printf("%lld ",query(1,1,n,l,r,0)); 95 } 96 return; 97 } 98 99 int main(){ 100 File("standard"); 101 work(); 102 return 0; 103 }