JZOJsenior4216.【NOIP2015模拟9.12】平方和

problem

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。


analysis

  • splay例题好伐……?

  • 通过左右旋维护两个东西,分别是平方和

  • 每次一个位置 x 加上a sqrsum[x] 就会加上 a2size[x]+2asum[x] sum[x] 会加上 asize[x]

  • 然后就可以用splay查找来进行插入节点操作

  • 然后愉快AC

splay具体走起这里


code

#include<bits/stdc++.h>
#define MAXN 200001
#define mod 7459

using namespace std;

long long tree[MAXN][3],sum[MAXN],sqrsum[MAXN];
long long a[MAXN],father[MAXN],size[MAXN],flag[MAXN];
int n,m,root;
char s[11];

void downdata(int x)
{
    if (!flag[x])return;
    if (tree[x][1])
    {
        flag[tree[x][1]]+=flag[x];
    }
    if (tree[x][2])
    {
        flag[tree[x][2]]+=flag[x];
    }
    sqrsum[x]=(((sqrsum[x]+((flag[x]*flag[x])%mod)*size[x])%mod)+2*flag[x]*sum[x])%mod;
    sum[x]=sum[x]+flag[x]*size[x];
    tree[x][0]+=flag[x];
    flag[x]=0;
}

void left_rotate(int x)
{
    downdata(father[x]);
    downdata(x);
    int y=father[x],z=father[y];
    father[x]=z,father[y]=x;
    if (z==0)root=x;
    else
    {
        if (tree[z][1]==y)
        {
            tree[z][1]=x;
        }
        else tree[z][2]=x;
    }

    if (tree[x][1])
    {
        father[tree[x][1]]=y;
    }
    tree[y][2]=tree[x][1];
    tree[x][1]=y;

    size[y]=size[tree[y][1]]+size[tree[y][2]]+1;
    size[x]=size[y]+size[tree[x][2]]+1;

    sum[y]=(sum[tree[y][1]]+sum[tree[y][2]]+tree[y][0])%mod;
    sum[x]=(sum[y]+sum[tree[x][1]]+tree[x][0])%mod;

    sqrsum[y]=(sqrsum[tree[y][1]]+sqrsum[tree[y][2]]+tree[y][0]*tree[y][0])%mod;
    sqrsum[x]=(sqrsum[y]+sqrsum[tree[x][2]]+tree[x][0]*tree[x][0])%mod;
}

void right_rotate(int x)
{
    downdata(father[x]);
    downdata(x);
    int y=father[x],z=father[y];
    father[x]=z,father[y]=x;

    if (z==0)root=x;
    else
    {
        if (tree[z][1]==y)
        {
            tree[z][1]=x;
        }
        else tree[z][2]=x;
    }
    if (tree[x][2])
    {
        father[tree[x][2]]=y;
    }
    tree[y][1]=tree[x][2];
    tree[x][2]=y;

    size[y]=size[tree[y][1]]+size[tree[y][2]]+1;
    size[x]=size[tree[x][1]]+size[y]+1;

    sum[y]=(sum[tree[y][1]]+sum[tree[y][2]]+tree[y][0])%mod;
    sum[x]=(sum[tree[x][1]]+sum[y]+tree[x][0])%mod;

    sqrsum[y]=(sqrsum[tree[y][1]]+sqrsum[tree[y][2]]+tree[y][0]*tree[y][0])%mod;
    sqrsum[x]=(sqrsum[tree[x][1]]+sqrsum[y]+tree[x][0]*tree[x][0])%mod;
}

void splay(int x,int y)
{
    if (x==y || x==0)return;
    while (father[x]!=y)
    {
        if (father[father[x]]==y)
        {
            if (tree[father[x]][1]==x)
            {
                right_rotate(x);
            }
            else left_rotate(x);
        }
        else
        {
            if (tree[father[father[x]]][1]==father[x] && tree[father[x]][1]==x)
            {
                right_rotate(father[x]);
                right_rotate(x);
            }
            else if (tree[father[father[x]]][1]==father[x] && tree[father[x]][2]==x)
            {
                left_rotate(x);
                right_rotate(x);
            }
            else if (tree[father[father[x]]][2]==father[x] && tree[father[x]][1]==x)
            {
                right_rotate(x);
                left_rotate(x);
            }
            else if (tree[father[father[x]]][2]==father[x] && tree[father[x]][2]==x)
            {
                left_rotate(father[x]);
                left_rotate(x);
            }
        }
    }
}

int find(int x,int y)
{
    if (tree[x][1])
    {
        downdata(tree[x][1]);
    }
    if (tree[x][2])
    {
        downdata(tree[x][2]);
    }
    if (y==size[tree[x][1]]+1)return x;
    else
    {
        if (y<size[tree[x][1]]+1)return find(tree[x][1],y);
        else return find(tree[x][2],y-size[tree[x][1]]-1);
    }
}

int main()
{   
    //freopen("readin.txt","r",stdin);

    scanf("%d",&n); 
    root=1,tree[1][2]=2;

    for (int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i+1]);
        father[i+1]=i;
        tree[i+1][0]=a[i+1];
        tree[i+1][2]=i+2;
        size[i+1]=n+2-i;
    }
    n+=2;
    for (int i=n-1;i>=1;i--)
    {
        sum[i]=(sum[i+1]+a[i])%mod;
        sqrsum[i]=(sqrsum[i+1]+a[i]*a[i])%mod;
    }
    size[1]=n,size[n]=1;
    father[n]=n-1;
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%s%d%d",&s,&x,&y);
        if (s[0]=='Q')
        {
            int j=find(1,x),k=find(1,y+2);
            splay(j,1),splay(k,j);
            printf("%lld\n",(sqrsum[tree[k][1]]+mod)%mod);
        }
        else if (s[0]=='I')
        {
            int j=find(1,x),k=find(1,x+1);
            splay(j,1),splay(k,j);
            tree[++n][0]=y,tree[n][1]=tree[n][2]=0;
            father[n]=k;
            tree[k][1]=n;
            sum[n]=y%mod,sqrsum[n]=y*y%mod;
            size[n]=1;
            sum[j]=(sum[j]+y)%mod,sum[k]=(sum[k]+y)%mod;
            sqrsum[j]=(sqrsum[j]+y*y)%mod,sqrsum[k]=(sqrsum[k]+y*y)%mod;
            size[j]++,size[k]++; 
        }
        else
        {
            scanf("%d",&z);
            int j=find(1,x),k=find(1,y+2);
            splay(j,1),splay(k,j);
            flag[tree[k][1]]+=z;
            downdata(tree[k][1]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值