【NOIP2015模拟9.12】平方和

来源:互联网 发布:人工智能介绍英文文章 编辑:程序博客网 时间:2024/06/07 03:28

Description

给出一个N个整数构成的序列,有M次操作,每次操作有一下三种:
①Insert Y X,在序列的第Y个数之前插入一个数X;
②Add L R X,对序列中第L个数到第R个数,每个数都加上X;
③Query L R,询问序列中第L个数到第R个数的平方和。

Input

第一行一个正整数N,表示初始序列长度。
第二行N个整数Ai,表示初始序列中的数。
第三行一个正整数M,表示操作数。
接下来M行,每行一种操作。

Output

对于每一个Query操作输出答案。由于答案可能很大,请mod 7459后输出。

Sample Input

5
1 2 3 4 5
5
Query 1 3
Insert 2 5
Query 2 4
Add 5 6 7
Query 1 6

Sample Output

14
38
304
样例解释:
第二次操作后的序列:1,5,2,3,4,5。
第四次操作后的序列:1,5,2,3,11,12。

Data Constraint

30%的数据满足N≤1,000,M≤1,000。
另外20%的数据满足N≤100,000,M≤100,000,且不存在Insert操作。
100%的数据满足N≤100,000,M≤100,000,且Add和Insert操作中|X|≤1000,|Ai|≤1000。

Solution

这题可以用离线线段树的方法来做,但是比较复杂,码量较大
我用的是splay做
维护平方和只需要维护和,大小还有平方和就行了
因为(a+x)2=a2+2ax+x2
第一项通过维护原来的平方和
第二项通过维护和
第三项就是lazy

Code

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define N 201000#define mo 7459#define ll long longusing namespace std;int t[N][2],fa[N],lz[N],tot,root,s[N],n;ll size[N],sum[N],d[N],ssum[N];void update(int x){    size[x]=size[t[x][0]]+size[t[x][1]]+1;    sum[x]=(sum[t[x][0]]+sum[t[x][1]]+d[x])%mo;    ssum[x]=(ssum[t[x][0]]+ssum[t[x][1]]+d[x]*d[x])%mo;}void down(int x,ll y){    ssum[x]=(ssum[x]+sum[x]*y*2ll+y*y*size[x])%mo;    sum[x]=(sum[x]+y*size[x])%mo;    d[x]=(d[x]+y+mo)%mo;lz[x]=(lz[x]+y+mo)%mo;}void xc(int x){    for(;x;x=fa[x]) s[++s[0]]=x;    for(;s[0];s[0]--)    {        int y=s[s[0]];        if(lz[y]!=0)        {            down(t[y][0],lz[y]);down(t[y][1],lz[y]);            lz[y]=0;        }    }}int lr(int x){return x==t[fa[x]][1];}void rotate(int x){    int y=fa[x],k=lr(x);    t[y][k]=t[x][1-k];if(t[x][1-k]) fa[t[x][1-k]]=y;    fa[x]=fa[y];if(fa[y]) t[fa[y]][lr(y)]=x;    t[x][1-k]=y;fa[y]=x;    update(y);update(x);}void splay(int x,int y){    xc(x);    while(fa[x]!=y)    {        if(fa[fa[x]]!=y)            if(lr(x)==lr(fa[x])) rotate(fa[x]);            else rotate(x);        rotate(x);    }    if(y==0) root=x;}int kth(int r,int x){    if(size[t[r][0]]+1==x) return r;    if(size[t[r][0]]>=x) return kth(t[r][0],x);    else return kth(t[r][1],x-size[t[r][0]]-1);}int main(){    scanf("%d",&n);    fa[1]=2;t[2][0]=1;update(1);    fo(i,1,n)    {        int x;scanf("%d",&x);        d[i+1]=(x+mo)%mo;fa[i+1]=i+2;t[i+2][0]=i+1;update(i+1);    }    root=n+2;update(n+2);tot=n+2;    int ac;scanf("%d\n",&ac);    for(;ac;ac--)    {        char ch;scanf("%c",&ch);        if(ch=='Q')        {            int x,y;scanf("uery %d %d\n",&x,&y);            x=kth(root,x);y=kth(root,y+2);            splay(x,0);splay(y,x);            printf("%d\n",ssum[t[y][0]]);        }        if(ch=='I')        {            int x,y,z;scanf("nsert %d %d\n",&x,&z);            z=(z+mo)%mo;            y=kth(root,x+1);x=kth(root,x);            splay(x,0);splay(y,x);            t[y][0]=++tot;fa[tot]=y;d[tot]=z;            update(tot);update(y);update(x);        }        if(ch=='A')        {            int x,y,z;scanf("dd %d %d %d\n",&x,&y,&z);            x=kth(root,x);y=kth(root,y+2);            splay(x,0);            splay(y,x);            down(t[y][0],z);        }    }}
原创粉丝点击