uoj#228 基础数据结构练习题

题面: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\n",query(1,1,n,l,r,0));
 95     }
 96     return;
 97 }
 98 
 99 int main(){
100     File("standard");
101     work();
102     return 0;
103 }

 

posted @ 2017-03-31 18:50  wfj_2048  阅读(350)  评论(1编辑  收藏  举报