hdu3468 splay

来源:互联网 发布:知乎体格式 编辑:程序博客网 时间:2024/06/10 08:22

题意:其实就是区间的加法和询问区间的和

解法:主要为了尝试一下splay维护区间和 因为之前只写过splay区间加法维护 

然后觉得很神奇啊 左右两个节点是不算内的,以前写单点都没有发现这一点吧

#include<cstdio>#include<iostream>using namespace std;typedef long long ll;#define ls ch[rt][0]#define rs ch[rt][1]#define rrs ch[root][1]#define rls ch[root][0]#define maxn 222222int n,m;int ch[maxn][2],fa[maxn],root,num[maxn],cnt;ll sum[maxn],add[maxn],a[maxn],val[maxn];inline void node(int rt){fa[rt]=sum[rt]=add[rt]=ls=rs=0;num[rt]=1;}inline void up(int rt){    sum[rt]=val[rt]+sum[ls]+sum[rs];    num[rt]=num[ls]+num[rs]+1;}inline void down(int rt){    if(add[rt]){        if(ls)add[ls]+=add[rt],val[ls]+=add[rt],sum[ls]+=add[rt]*(num[ls]);        if(rs)add[rs]+=add[rt],val[rs]+=add[rt],sum[rs]+=add[rt]*(num[rs]);        add[rt]=0;    }}inline void rot(int rt){    int f=fa[rt],side=ch[f][1]==rt,ll=ch[rt][!side];    fa[ll]=f,ch[f][side]=ll;    fa[rt]=fa[f],ch[fa[f]][ch[fa[f]][1]==f]=rt;    fa[f]=rt,ch[rt][!side]=f;    up(f),up(rt);}void splay(int rt,int aim){    while(fa[rt]!=aim){        down(rt);        int f=fa[rt],ff=fa[f];        if(ff==aim)rot(rt);        else if((ch[f][1]==rt)==(ch[ff][1]==f))rot(f),rot(rt);        else rot(rt),rot(rt);    }if(!aim)root=rt;}inline void find(int tot,int sub){    int rt=sub;    while(1){        down(rt);        if(num[ls]+1==tot)break;        if(num[ls]>=tot)rt=ls;        else tot-=num[ls]+1,rt=rs;    }splay(rt,fa[sub]);}void _add(int l,int r,ll w){    find(l,root);find(r-l+2,rrs);    int rt=ch[rrs][0];    sum[rt]+=w*num[rt];add[rt]+=w;val[rt]+=w;}void build(int n){    cnt=0;node(0);num[0]=0;    node(++cnt);    for(int i=2;i<=n+1;++i){        node(++cnt);fa[i-1]=i;ch[i][0]=i-1;val[i]=a[i];up(i);    }root=cnt;    node(++cnt);fa[cnt]=cnt-1;ch[cnt-1][1]=cnt;up(root);//    for(int i=1;i<=n+2;++i)//        printf("%d %d %d %lld\n",i,fa[i],num[i],sum[i]);    }char op[111];int l,r;int main(){    while(~scanf("%d%d",&n,&m)){        for(int i=2;i<=n+1;++i)scanf("%lld",&a[i]);        build(n);        while(m--){            scanf("%s%d%d",op,&l,&r);            if(*op=='Q'){                find(l,root);find(r-l+2,rrs);//                printf("%lld %lld\n",val[root],val[rrs]);                printf("%lld\n",sum[ch[rrs][0]]);            }else if(*op=='C'){                ll w;scanf("%lld",&w);                _add(l,r,w);            }        }    }    return 0;}


0 0