zoukankan      html  css  js  c++  java
  • 牛客网练习赛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;
    }
  • 相关阅读:
    把Linq查询返回的var类型的数据 转换为DataTable EF连接查询
    无法更新 EntitySet 因为它有一个 DefiningQuery
    MVC上传文件
    MySql删除表、数据
    LINQ to Entities 不支持 LINQ 表达式节点类型“ArrayIndex”。
    MVC仓储使用join
    MVC仓储执行存储过程报错“未提供该参数”
    Newtonsoft.Json自动升级版本号,导致dll冲突
    MVC中构建Linq条件、排序、Selector字段过滤
    AutoMapper
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9746388.html
Copyright © 2011-2022 走看看