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 long
using 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);
}
}
}