poj 3468 A Simple Problem with Integers splay

题意:有两种操作: 1. C l r x: 区间[l,r]的数加x。   2. Q  l r : 查询区间[l,r]的和。

思路:线段树的裸题,只是为了练习splay。详见代码:

/*********************************************************
  file name: poj3468.cpp
  author : kereo
  create time:  2015年01月28日 星期三 15时03分07秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=100000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=100000000+7;
#define L(x) (x->ch[0])
#define R(x) (x->ch[1])
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int n,m,cnt,top;
int st[MAXN];
char str[N];
ll num[MAXN];
struct node{
    int sz;
    ll val,sum,tag;
    node *fa,*ch[2];
}nod[MAXN],nil,*root,*null;
struct Splay{
    void rotate(node *x,int d){
        node *y=x->fa;
        push_down(y); push_down(x);
        y->ch[d^1]=x->ch[d];
        if(x->ch[d]!=null) x->ch[d]->fa=y;
        x->fa=y->fa;
        if(y->fa!=null){
            int d1=y->fa->ch[0] == y ? 0 : 1;
            y->fa->ch[d1]=x;
        }
        y->fa=x; x->ch[d]=y;
        push_up(y);
    }
    void splay(node *x,node *fa){
        while(x->fa!=fa){
            push_down(x);
            node *y=x->fa;
            if(y->fa == fa){
                int d=y->ch[0] == x ? 1 : 0;
                rotate(x,d);
            }
            else{
                int d=y->fa->ch[0] == y ? 1 : 0;
                if(y->ch[d] == x){
                    rotate(x,d^1); rotate(x,d);
                }
                else{
                    rotate(y,d); rotate(x,d);
                }
            }
        }
        push_up(x);
        if(fa == null) root=x;
    }
    void rotateto(int k,node *fa){
        node *rt=root;
        push_down(rt);
        while(L(rt)->sz!=k){
            if(L(rt)->sz>k)
                rt=L(rt);
            else{
                k-=(L(rt)->sz+1);
                rt=R(rt);
            }
            push_down(rt);
        }
        splay(rt,fa);
    }
    void init(){
        cnt=top=0;
        nil.sz=nil.val=nil.sum=nil.tag=0;
        null=&nil; root=null;
        newnode(root,null,0); 
        newnode(R(root),root,0);
        for(int i=1;i<=n;i++)
            scanf("%lld",&num[i]);
        build(L(R(root)),R(root),1,n);
        push_up(R(root)); push_up(root);
    }
    void newnode(node *&x,node *fa,int val){
        if(top) 
            x=&nod[st[--top]];
        else 
            x=&nod[++cnt];
        x->sz=1; x->val=x->sum=val; 
        x->tag=0; x->fa=fa; x->ch[0]=x->ch[1]=null;
    }
    void push_down(node *rt){
         if(rt->tag){
            rt->val+=rt->tag;
            L(rt)->tag+=rt->tag; R(rt)->tag+=rt->tag;
            L(rt)->sum+=L(rt)->sz*rt->tag;
            R(rt)->sum+=R(rt)->sz*rt->tag;
            rt->tag=0;
         }
    }
    void push_up(node *rt){
         rt->sz=L(rt)->sz+R(rt)->sz+1;
         rt->sum=rt->val+L(rt)->sum+R(rt)->sum;
    }
    void build(node *&rt,node *fa,int l,int r){
        if(l>r)
            return ;
        int mid=(l+r)>>1;
        newnode(rt,fa,num[mid]);
        build(L(rt),rt,l,mid-1); build(R(rt),rt,mid+1,r);
        push_up(rt);
    }
    void update(int l,int r,ll x){
        rotateto(l-1,null); 
        rotateto(r+1,root);
        node *rt=L(R(root));
        rt->tag+=x;
        rt->sum+=rt->sz*x;
    }
    ll query(int l,int r){
        rotateto(l-1,null);
        rotateto(r+1,root);
        return L(R(root))->sum;
    }
}spt;
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        spt.init();
        while(m--){
            scanf("%s",str);
            if(str[0] == 'C'){
                int l,r;
                ll x;
                scanf("%d%d%lld",&l,&r,&x);
                spt.update(l,r,x);
            }
            else{
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%lld\n",spt.query(l,r));
            }
        }
    }
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值