其他分享
首页 > 其他分享> > 1011 外挂 线段树 数学思维

1011 外挂 线段树 数学思维

作者:互联网

 链接:https://ac.nowcoder.com/acm/contest/26896/1011
来源:牛客网

题目描述

我的就是我的,你也是我的,记住了,狐狸!                                                                       ——韩信-白龙吟
对于打赌输了的小T会遭受到制裁,小s修改了数据库使他可以派出许多军队来围攻小T.
很不幸,小T与小s打赌打输了,现在小T遭受着枪林弹雨与十面埋伏,因为小T是神所以他决定要扭转局势。
他要修改数据库!
数据总库的信号墙有n个电极插头,每个插头有一个信号aia_iai​,
小T可以使在区间[ l,r ][\ l,r\ ][ l,r ]内的所有信号加上一个值k。
对于区间[ l,r ][\ l,r\ ][ l,r ]的信号强度有一个计算公式:
我们定义 f(k)=ak×∑j=k+1rajf(k)=a_k \times \sum_{j=k+1}^r a_jf(k)=ak​×∑j=k+1r​aj​
则信号强度就为: ∑i=lrf(i)\sum_{i=l}^r f(i)∑i=lr​f(i)
你可以认为f(i)就是第i个插头的信号强度。
现在小T一会儿修改信号值,一会儿询问信号强度,你是数据库的管理员,为了不被小TD,所以你要告诉他信号强度是多少。

注:本系列题不按难度排序哦

输入描述:

第一行两个整数n,Q

第二行n个整数代表a

后Q行代表操作:

一操作:1 l r x1\ l\ r\ x1 l r x代表区间[ l,r ][\ l,r\ ][ l,r ]加x。

二操作:2 l r2\ l\ r2 l r代表区间询问。

输出描述:

每一行一个数字,表示对于一个二操作的答案。
示例1

输入

复制
5 2
1 2 3 4 5
1 1 2 1
2 1 2

输出

复制
6

说明

样例解释:1 1 2 1使a[1]~a[2]的值每个都加了1, 即a[1]=2, a[2]=3,所以2 1 2=a[1]*a[2]=2*3=6   保证所有二操作的答案都是在long longlong\ longlong long范围内(如果你不相信,可以写高精)。

时空限制为标程的5倍,放心卡常。

备注:

100%  1≤n,Q≤105100 \% \ \ 1 \le n,Q \le 10^5100%  1≤n,Q≤105 对于所有ai≤100a_i \le 100ai​≤100

分析

题意要求的是 a1 * a2 + a2 *a3 + a3 * a1 

由 (a1+ a2 + a3) ^ 2 = a1 ^2  + a2 ^ 2 + a3 ^ 2 + a1 * a2 * 2 + a1 * a3 * 2 + a2 * a3 * 2

所以知道区间和 t1 区间平方和t2

t1 ^ 2 = t2 + 2 *答案

答案 = ( t1 ^ 2 - t2 ) / 2

//-------------------------代码----------------------------

#define int ll
const int N = 1e5+10;
int n,m,q;

int a[N];

struct node {
    int l,r,s1,s2,la1,la2;
} tr[N * 4];

void push_up(int u) {
    tr[u].s1 = tr[tr_ul].s1 + tr[tr_ur].s1;
    tr[u].s2 = tr[tr_ul].s2 + tr[tr_ur].s2;
}

void push_down(int u) {
    if(tr[u].la1 == 0 && tr[u].la2 == 1)rt;
    int x = tr[u].la1;tr[u].la1 = 0;
    tr[tr_ul].s2 += 2 * tr[tr_ul].s1 * x + x * x * tr_len(tr_ul);
    tr[tr_ur].s2 += 2 * tr[tr_ur].s1 * x + x * x * tr_len(tr_ur);
    tr[tr_ul].s1 += tr_len(tr_ul) * x;
    tr[tr_ur].s1 += tr_len(tr_ur) * x;
    tr[tr_ul].la1 += x;tr[tr_ur].la1 += x;
}

void build(int u,int l,int r) {
    tr[u]={l,r,0,0,0};
    if(l==r){tr[u].s1=a[l];tr[u].s2=a[l]*a[l];return ;}
    int mid = l + r >> 1;
    build(tr_ul,l,mid);build(tr_ur,mid+1,r);
    push_up(u);
}

int t1,t2;
void query(int u,int l,int r) {
    if(l <= tr[u].l && tr[u].r <= r) {
        t1 += tr[u].s1;
        t2 += tr[u].s2;
        rt;
    }
    push_down(u);
    if(l <= tr_mid) query(tr_ul,l,r);
    if(tr_mid <  r) query(tr_ur,l,r);
    push_up(u);
}

void modify(int u,int l,int r,int c) {
    if(l <= tr[u].l && tr[u].r <= r) {
        tr[u].s2+=2*tr[u].s1*c+c*c*tr_len(u);
        tr[u].s1+=c*tr_len(u);
        tr[u].la1+=c;
        return ;
    }
    push_down(u);
    if(l <= tr_mid) modify(tr_ul,l,r,c);
    if(tr_mid <  r) modify(tr_ur,l,r,c);
    push_up(u);
}

void solve()
{
//    cin>>n>>m;
    cin>>n>>q;
    fo(i,1,n) cin>>a[i];
    build(1,1,n);
    fo(o,1,q) {
        int op,l,r;cin>>op>>l>>r;
        if(op == 1) {
            int x;cin>>x;
            modify(1,l,r,x);
        } else if(op == 2) {
            t1 = t2 = 0;
            query(1,l,r);
            cout<<(t1 * t1 - t2) / 2<<endl;
        }
    }
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

标签:外挂,int,s2,线段,tr,ur,ul,1011,s1
来源: https://www.cnblogs.com/er007/p/16563513.html