AC日记——线段树练习三 codevs 1082 (分块尝试)
思路:
分块;
来,上代码:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 200005 #define ll long long ll n,m,flag[maxn],size,bel[maxn],dis[maxn]; ll sum[maxn],li[maxn],ri[maxn],blo,si[maxn]; inline void in(ll &now) { ll if_z=1;now=0; char Cget=getchar(); while(Cget>'9'||Cget<'0') { if(Cget=='-') if_z=-1; Cget=getchar(); } while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } now*=if_z; } int main() { in(n),size=sqrt(n);ll pos=0,x; for(ll i=1;i<=n;i++) { in(dis[i]); if(pos==0) li[++blo]=i; pos++,sum[blo]+=dis[i],bel[i]=blo; if(pos==size) pos=0,ri[blo]=i; } ri[blo]=n; for(ll i=1;i<=blo;i++) si[i]=ri[i]-li[i]+1; ll ty,l,r;in(m); while(m--) { in(ty),in(l),in(r); if(ty==1) { in(x); for(ll i=bel[l];i<=bel[r];i++) { if(l<=li[i]&&r>=ri[i]) flag[i]+=x,sum[i]+=si[i]*x; else { for(ll j=max(l,li[i]);j<=min(r,ri[i]);j++) dis[j]+=x,sum[i]+=x; } } } else { ll ans=0; for(ll i=bel[l];i<=bel[r];i++) { if(l<=li[i]&&r>=ri[i]) ans+=sum[i]; else for(ll j=max(li[i],l);j<=min(ri[i],r);j++) ans+=dis[j]+flag[i]; } printf("%lld\n",ans); } } return 0; }