牛客网练习赛t2(线段树)

题解:

好像因为他说了

数据范围全部在ll以内

所以直接暴力就可以过了

比较正常是用线段树来维护

洛谷上有道模板题是支持加,乘,区间和

而这题还多了区间平方和的操作

按照那题的操作

我们维护的时候保证先乘再加

a1^2+a2^2+a3^2

我们考虑先*x再+y 以及先+y再*x两种操作

(a1*x+y)^2+(a2*x+y)^2+(a3*x+y)^2

x*x*(a1+y)^2

于是我们维护操作的时候是这样的

平方和+=2*sum1*乘法标记*lazy值+乘法标记*乘法标记*lazy值

关键在于这个2*sum1*乘法标记*lazy值

看第一种情况展开项为2*a1*x*y 符合

第二种情况为2*x*x*a1*y  而这个我们已经对y乘了x 所以也是对的

代码:

 

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define ll long long
#define mid ((h+t)/2)
const int N=2e4;
int a[N],n,m;
struct sgt{
    ll sum[N*4],sum2[N*4],lazy[N*4];
    ll lazy3[N*4];
    sgt()
    {
        rep(i,0,N*4-1) lazy3[i]=1;
    }
    IL void updata(int x)
    {
        sum[x]=sum[x*2]+sum[x*2+1];
        sum2[x]=sum2[x*2]+sum2[x*2+1];
    }
    IL void down(int x,int h,int t)
    {
        ll t1=sum[x*2],t2=sum[x*2+1],t3=lazy3[x];
        if (lazy3[x]!=1)
        {
            sum[x*2]*=lazy3[x];
            sum[x*2+1]*=lazy3[x];
            sum2[x*2]*=lazy3[x]*lazy3[x];
            sum2[x*2+1]*=lazy3[x]*lazy3[x];
            lazy3[x*2]*=lazy3[x];
            lazy3[x*2+1]*=lazy3[x];
            lazy[x*2]*=lazy3[x];
            lazy[x*2+1]*=lazy3[x];
            lazy3[x]=1;
        }
            sum2[x*2]+=2*t1*lazy[x]*t3+(mid-h+1)*lazy[x]*lazy[x];
            sum2[x*2+1]+=2*t2*lazy[x]*t3+(t-mid)*lazy[x]*lazy[x];
        if (lazy[x])
        {
            sum[x*2]+=(mid-h+1)*lazy[x];
            sum[x*2+1]+=(t-mid)*lazy[x];
            lazy[x*2]+=lazy[x]; lazy[x*2+1]+=lazy[x];
            lazy[x]=0;
        }
    }
    void build(int x,int h,int t)
    {
        if (h==t)
        {
            sum[x]=a[h]; sum2[x]=a[h]*a[h]; return;
        }
        build(x*2,h,mid); build(x*2+1,mid+1,t);
        updata(x);
    }
    void add(int x,int h,int t,int h1,int t1,ll k)
    {
        if (h1<=h&&t<=t1)
        {
            lazy[x]+=k;
            sum2[x]=sum2[x]+2*k*sum[x]+(t-h+1)*k*k;
            sum[x]=sum[x]+(t-h+1)*k;
            return;
        }
        down(x,h,t);
        if (h1<=mid) add(x*2,h,mid,h1,t1,k);
        if (mid<t1) add(x*2+1,mid+1,t,h1,t1,k);
        updata(x);
    }
    void change(int x,int h,int t,int h1,int t1,ll k)
    {
        if (h1<=h&&t<=t1)
        {
            lazy[x]*=k;lazy3[x]*=k;
            sum2[x]=sum2[x]*k*k; sum[x]=sum[x]*k;
            return;
        }
        down(x,h,t);
        if (h1<=mid) change(x*2,h,mid,h1,t1,k);
        if (mid<t1) change(x*2+1,mid+1,t,h1,t1,k);
        updata(x);
    }
    ll query1(int x,int h,int t,int h1,int t1)
    {
        if (h1<=h&&t<=t1) return(sum[x]);
        ll ans=0;
        down(x,h,t);
        if (h1<=mid) ans+=query1(x*2,h,mid,h1,t1);
        if (mid<t1) ans+=query1(x*2+1,mid+1,t,h1,t1);
        return(ans);
    }
    ll query2(int x,int h,int t,int h1,int t1)
    {
        if (h1<=h&&t<=t1) return(sum2[x]);
        ll ans=0;
        down(x,h,t);
        if (h1<=mid) ans+=query2(x*2,h,mid,h1,t1);
        if (mid<t1) ans+=query2(x*2+1,mid+1,t,h1,t1);
        return(ans);
    }
}S;
int main()
{
    ios::sync_with_stdio(false);
  cin>>n>>m;
  rep(i,1,n) cin>>a[i];
  S.build(1,1,n);
    rep(i,1,m)
    {
        int kk,x1,x2,y;
        cin>>kk;
        if (kk==1)
        {
            cin>>x1>>x2;
            cout<<S.query1(1,1,n,x1,x2)<<endl;
        }
        if (kk==2)
        {
            cin>>x1>>x2;
            cout<<S.query2(1,1,n,x1,x2)<<endl;
        }
        if (kk==3)
        {
            cin>>x1>>x2>>y;
            S.change(1,1,n,x1,x2,y);
        }
        if (kk==4)
        {
            cin>>x1>>x2>>y;
            S.add(1,1,n,x1,x2,y);
        }
    }
    return 0;
}

 

posted @ 2018-10-05 23:54  尹吴潇  阅读(111)  评论(0编辑  收藏  举报