poj 3468 A Simple Problem with Integers(splay tree解法)

A Simple Problem with Integers
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 25486 Accepted: 7001
Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

Source

题目:http://poj.org/problem?id=3468

分析:这题只是一道线段树的题,由于傻崽大神的splay模板就是这题,只好将就着做了= =,用splay实在很慢啊

ps:近期状态稍微恢复,之前没状态,完全看不懂模板啊可怜

等做些题后再整理成模板= =

代码(只是稍微改改风格而已):

#include<cstdio>
const int mm=222222;
int num[mm];
struct SplayTree
{
    int C[mm][2],S[mm],F[mm],val[mm],add[mm];
    int root,size,l,r,d;
    long long sum[mm];
    void rotate(int x,int f)
    {
        int y=F[x];
        pushdown(y);
        pushdown(x);
        C[y][!f]=C[x][f];
        F[C[x][f]]=y;
        F[x]=F[y];
        if(F[x])C[F[y]][C[F[y]][1]==y]=x;
        C[x][f]=y;
        F[y]=x;
        updata(y);
    }
    void splay(int x,int goal)
    {
        pushdown(x);
        while(F[x]!=goal)
            if(F[F[x]]==goal)rotate(x,C[F[x]][0]==x);
            else
            {
                int y=F[x],f=(C[F[y]][0]==y);
                if(C[y][f]==x)rotate(x,!f);
                else rotate(y,f);
                rotate(x,f);

            }
        updata(x);
        if(!goal)root=x;
    }
    void select(int k,int goal)
    {
        int x=root;
        pushdown(x);
        while(S[C[x][0]]!=k)
        {
            if(S[C[x][0]]>k)x=C[x][0];
            else k-=(S[C[x][0]]+1),x=C[x][1];
            pushdown(x);
        }
        splay(x,goal);
    }
    void plus(int x,int d)
    {
        add[x]+=d;
        sum[x]+=(long long)d*S[x];
    }
    void pushdown(int x)
    {
        if(add[x])
        {
            val[x]+=add[x];
            for(int i=0;i<2;++i)plus(C[x][i],add[x]);
            add[x]=0;
        }
    }
    void updata(int x)
    {
        S[x]=S[C[x][0]]+S[C[x][1]]+1;
        sum[x]=add[x]+val[x]+sum[C[x][0]]+sum[C[x][1]];
    }
    void newnode(int &x,int v)
    {
        x=++size;
        C[x][0]=C[x][1]=F[x]=0;
        sum[x]=val[x]=v;
        S[x]=1;
        add[x]=0;
    }
    void make(int &x,int l,int r,int f)
    {
        if(l>r)return;
        int m=(l+r)>>1;
        newnode(x,num[m]);
        make(C[x][0],l,m-1,x);
        make(C[x][1],m+1,r,x);
        F[x]=f;
        updata(x);
    }
    void prepare(int n)
    {
        C[0][0]=C[0][1]=S[0]=F[0]=0;
        val[0]=sum[0]=add[0]=0;
        root=size=0;
        newnode(root,0);
        newnode(C[root][1],0);
        F[size]=root;
        S[root]=2;
        make(C[C[root][1]][0],0,n-1,C[root][1]);
        updata(C[root][1]);
        updata(root);
    }
    void addnum()
    {
        scanf("%d%d%d",&l,&r,&d);
        select(l-1,0);
        select(r+1,root);
        plus(C[C[root][1]][0],d);
    }
    void answer()
    {
        scanf("%d%d",&l,&r);
        select(l-1,0);
        select(r+1,root);
        printf("%lld\n",sum[C[C[root][1]][0]]);
    }
}spt;
int main()
{
    int i,n,m;
    char op[2];
    scanf("%d%d",&n,&m);
    for(i=0;i<n;++i)scanf("%d",&num[i]);
    spt.prepare(n);
    while(m--)
    {
        scanf("%s",op);
        if(op[0]=='C')spt.addnum();
        else spt.answer();
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值