POJ 3468 A Simple Problem with Integers 【splay树入门题】

来源:互联网 发布:振动分析软件 编辑:程序博客网 时间:2024/04/30 11:27

Description

给出了一个序列,你需要处理如下两种询问。

"C a b c"表示给[a, b]区间中的值全部增加c (-10000 c  10000)

"Q a b" 询问[a, b]区间中所有值的和。

Input

第一行包含两个整数N,Q。1 N,Q  100000.

第二行包含n个整数,表示初始的序列A (-1000000000 Ai 1000000000)。

接下来Q行询问,格式如题目描述。

Output

对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。

Sample Input

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

Sample Output

455915

由于强大的splay有强大的区间更新功能,完全可以胜任,但是速度慢了好多……对比这篇:

hdu4267A Simple Problem with Integers【树状数组区间更新/单点查询】

注意splay函数while里面的5个push_down模板上有是由于存在反转操作,对于本题而言就不能再算进去了==

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>using namespace std;#define Key_value ch[ch[root][1]][0]const int MAXN=500010;const int INF=0x3f3f3f3f;int pre[MAXN],ch[MAXN][2],key[MAXN],size[MAXN];int rev[MAXN],same[MAXN];int lx[MAXN],rx[MAXN],mx[MAXN];int root,tot1;int s[MAXN],tot2;int a[MAXN];int n,q;long long sum[MAXN];//debug部分void Treavel(int x){    if(x)    {        Treavel(ch[x][0]);        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d key=%2d, size= %2d, sum=%2d,rev=%2d same=%2d lx=%2d rx=%2d mx=%2d\n",x,ch[x][0],ch[x][1],pre[x],key[x],size[x],sum[x],rev[x],same[x],lx[x],rx[x],mx[x]);        Treavel(ch[x][1]);    }}void debug(){    printf("root%d\n",root);    Treavel(root);}void NewNode(int &r,int father,int k){    if(tot2)r=s[tot2--];    else r=++tot1;    pre[r]=father;    ch[r][0]=ch[r][1]=0;    key[r]=k;    sum[r]=k;    rev[r]=same[r]=0;    lx[r]=rx[r]=mx[r]=k;    size[r]=1;}void Update_Same(int r,int v){    if(!r)return;    key[r]+=v;    sum[r]+=(long long)v*size[r];    //Update_Same(ch[r][0],v);    //Update_Same(ch[r][1],v);  //  lx[r]=rx[r]=mx[r]=max(v,sum[r]);    same[r]+=v;}void Update_Rev(int r){    if(!r)return;    swap(ch[r][0],ch[r][1]);    swap(lx[r],rx[r]);    rev[r]^=1;//这里要注意,一定是异或1}void Push_Up(int r){    int lson=ch[r][0],rson=ch[r][1];    size[r]=size[lson]+size[rson]+1;    sum[r]=sum[lson]+sum[rson]+key[r];//    lx[r]=max(lx[lson],sum[lson]+key[r]+max(0,lx[rson]));//    rx[r]=max(rx[rson],sum[rson]+key[r]+max(0,rx[lson]));//    mx[r]=max(0,rx[lson])+key[r]+max(0,lx[rson]);//    mx[r]=max(mx[r],max(mx[lson],mx[rson]));}void Push_Down(int r){    if(same[r])    {        Update_Same(ch[r][0],same[r]);///        Update_Same(ch[r][1],same[r]);        same[r]=0;    }    if(rev[r])    {        Update_Rev(ch[r][0]);        Update_Rev(ch[r][1]);        rev[r]=0;    }}void Build(int &x,int l,int r,int father){    if(l>r)return;    int mid=(l+r)/2;    NewNode(x,father,a[mid]);    Build(ch[x][0],l,mid-1,x);    Build(ch[x][1],mid+1,r,x);    Push_Up(x);}void Init(){    root=tot1=tot2=0;    ch[root][0]=ch[root][1]=pre[root]=size[root]=same[root]=rev[root]=sum[root]=key[root]=0;//    lx[root]=rx[root]=mx[root]=-INF;    NewNode(root,0,-1);    NewNode(ch[root][1],root,-1);    for(int i=1;i<=n;i++)scanf("%d",&a[i]);///    Build(Key_value,1,n,ch[root][1]);    Push_Up(ch[root][1]);    Push_Up(root);}void Rotate(int x,int kind){    int y=pre[x];    Push_Down(y);    Push_Down(x);    ch[y][!kind]=ch[x][kind];    pre[ch[x][kind]]=y;    if(pre[y])        ch[pre[y]][ch[pre[y]][1]==y]=x;    pre[x]=pre[y];    ch[x][kind]=y;    pre[y]=x;    Push_Up(y);}void Splay(int r,int goal){    Push_Down(r);    while(pre[r]!=goal)    {        if(pre[pre[r]]==goal)        {         //   Push_Down(pre[r]);         //   Push_Down(r);            Rotate(r,ch[pre[r]][0]==r);        }        else        {         //   Push_Down(pre[pre[r]]);          //  Push_Down(pre[r]);        //    Push_Down(r);            int y=pre[r];            int kind=ch[pre[y]][0]==y;            if(ch[y][kind]==r)            {                Rotate(r,!kind);                Rotate(r,kind);            }            else            {                Rotate(y,kind);                Rotate(r,kind);            }        }    }    Push_Up(r);    if(goal==0)root=r;}int Get_Kth(int r,int k){    Push_Down(r);    int t=size[ch[r][0]]+1;    if(t==k)return r;    if(t>k)return Get_Kth(ch[r][0],k);    else return Get_Kth(ch[r][1],k-t);}////在第pos个数后插入tot个数//void Insert(int pos,int tot)//{//    for(int i=0;i<tot;i++)scanf("%d",&a[i]);//    Splay(Get_Kth(root,pos+1),0);//    Splay(Get_Kth(root,pos+2),root);//    Build(Key_value,0,tot-1,ch[root][1]);//    Push_Up(ch[root][1]);//    Push_Up(root);//}//void erase(int r)//{//    if(!r)return;//    s[++tot2]=r;//    erase(ch[r][0]);//    erase(ch[r][1]);//}////从第pos个数开始连续删除tot个数//void Delete(int pos,int tot)//{//    Splay(Get_Kth(root,pos),0);//    Splay(Get_Kth(root,pos+tot+1),root);//    erase(Key_value);//    pre[Key_value]=0;//    Key_value=0;//    Push_Up(ch[root][1]);//    Push_Up(root);//}//从第pos个数连续开始的tot个数修改为cvoid Make_Same(int pos,int tot,int c){    Splay(Get_Kth(root,pos),0);    Splay(Get_Kth(root,pos+tot+1),root);    Update_Same(Key_value,c);    Push_Up(ch[root][1]);    Push_Up(root);}////反转//void Reverse(int pos,int tot)//{//    Splay(Get_Kth(root,pos),0);//    Splay(Get_Kth(root,pos+tot+1),root);//    Update_Rev(Key_value);//    Push_Up(ch[root][1]);//    Push_Up(root);//}//求和long long Get_Sum(int pos,int tot){    Splay(Get_Kth(root,pos),0);    Splay(Get_Kth(root,pos+tot+1),root);    return sum[Key_value];}////得到最大和//int Get_MaxSum(int pos,int tot)//{//    Splay(Get_Kth(root,pos),0);//    Splay(Get_Kth(root,pos+tot+1),root);//    return mx[Key_value];//}void Inorder(int r){    if(!r)return;    Push_Down(r);    Inorder(ch[r][0]);    printf("%d ",key[r]);    Inorder(ch[r][1]);}int main(){    //freopen("cin.txt","r",stdin);    //freopen("out.txt","w",stdout);    while(~scanf("%d%d",&n,&q))    {        Init();        char op[20];        int x,y,z;        while(q--)        {            scanf("%s",op);//            if(op[0]=='I')//            {//                scanf("%d%d",&x,&y);//                Insert(x,y);//            }//            else if(op[0]=='D')//            {//                scanf("%d%d",&x,&y);//                Delete(x,y);//            }            if(op[0]=='C')            {                scanf("%d%d%d",&x,&y,&z);                Make_Same(x,y-x+1,z);            }//            else if(op[0]=='R')//            {//                scanf("%d%d",&x,&y);//                Reverse(x,y);//            }            else if(op[0]=='Q')            {                scanf("%d%d",&x,&y);                printf("%I64d\n",Get_Sum(x,y-x+1));            }//            else//            {//                printf("%d\n",Get_MaxSum(1,size[root]-2));//            }        }    }    return 0;}


0 0
原创粉丝点击