正题
题目链接:https://jzoj.net/senior/#main/show/4216
题目大意
一个序列要求支持操作
- 插入一个数
- 区间加上一个数
- 区间求平方和
解题思路
用线段树可以做到区间求平方和。
就是(a+b)2=a2+2ab+b2(a+b)^2=a^2+2ab+b^2(a+b)2=a2+2ab+b2也就是维护区间和平方和和区间个数即可。
但是因为要插入一个数所以我们用SplaySplaySplay维护即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=210000,XJQ=7459;
struct Splay_node{struct Tree_node{ll siz,sum,sqr,val,lazy; }a[N];ll t[N][2],fa[N];ll Dicrect(ll x){return (t[fa[x]][1]==x);}void Change(ll x,ll z){a[x].sqr+=2*a[x].sum*z+z*z*a[x].siz;a[x].val+=z;a[x].lazy+=z;a[x].sum+=z*a[x].siz;return;}void PushDown(ll x){if(a[x].lazy){Change(t[x][0],a[x].lazy);Change(t[x][1],a[x].lazy);a[x].lazy=0;}return;}void PushUp(ll x){a[x].sqr=a[t[x][0]].sqr+a[t[x][1]].sqr+a[x].val*a[x].val;a[x].sum=a[t[x][0]].sum+a[t[x][1]].sum+a[x].val;a[x].siz=a[t[x][0]].siz+a[t[x][1]].siz+1;}void DownData(ll x){if(!x) return;DownData(fa[x]);PushDown(x);}void Connect(ll x,ll y,ll son){t[y][son]=x;fa[x]=y;}void Rotate(ll x){ll y=fa[x],root=fa[fa[x]];ll ys=Dicrect(x),rs=Dicrect(y);ll z=t[x][ys^1];Connect(z,y,ys);Connect(y,x,ys^1);Connect(x,root,rs);PushUp(y);PushUp(x);return;}void Splay(ll x,ll f){DownData(x);while(fa[x]!=f){ll up=fa[x];if(fa[up]==f) Rotate(x);else if(Dicrect(x)==Dicrect(up))Rotate(up),Rotate(x);else Rotate(x),Rotate(x);}}ll Find(ll x,ll z) {PushDown(x);if(a[t[x][0]].siz>=z) return Find(t[x][0],z);if(a[t[x][0]].siz+1==z) return x;return Find(t[x][1],z-a[t[x][0]].siz-1);}
}T;
ll n,root,tot,m;
int main()
{scanf("%lld",&n);T.a[1].siz=1;for(ll i=1;i<=n;i++){scanf("%lld",&T.a[i+1].val);T.fa[i]=i+1;T.t[i+1][0]=i;T.PushUp(i+1);}T.fa[n+1]=n+2;T.t[n+2][0]=n+1;T.PushUp(n+2);root=tot=n+2;scanf("%lld",&m);while(m--){char op[8];ll l,r,z;scanf("%s",op);if(op[0]=='A'){scanf("%lld%lld%lld",&l,&r,&z);ll x=T.Find(root,l),y=T.Find(root,r+2);T.Splay(x,0);T.Splay(y,x);root=T.t[y][0];T.Change(T.t[y][0],z);T.Splay(T.t[y][0],0);}if(op[0]=='Q'){scanf("%lld%lld",&l,&r);ll x=T.Find(root,l),y=T.Find(root,r+2);T.Splay(x,0);T.Splay(y,x);root=x;printf("%lld\n",T.a[T.t[y][0]].sqr%XJQ);}if(op[0]=='I'){scanf("%lld%lld",&l,&z);ll x=T.Find(root,l),y=T.Find(root,l+1);T.Splay(x,0);T.Splay(y,x);T.fa[++tot]=y;T.a[tot].siz=1;T.a[tot].sqr=z*z;T.a[tot].sum=T.a[tot].val=z;T.t[y][0]=tot;T.Splay(tot,0);root=tot;}}
}