CF 295E Yaroslav and Points(Splay)

来源:互联网 发布:unity3d模型资源 编辑:程序博客网 时间:2024/05/10 13:13

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

对于比赛中的hime这种裸E爷不忍直视。

虽然是非常裸的数据结构,但是实在是代码捉鸡。。。。

首先用一个set维护一下,当前序列中的数。

排好序后建立Splay,至于修改操作,便是找到原来位置上的,删除之后,再找到需要插入的位置 。

感觉这个部分,我写得很麻烦,大概就是不断遍历。sad。。。。

至于查询部分,Splay肯定是找到区间,然后旋转到某棵子树。就行了

Splay维护一个子树的答案,然后还需要维护子树的序列和。

push_up的时候,根据左右子树关系就OK了。。。。

一般这种数据结构我都会RE几次,死循环。。。2333333333333

AC时刻,不能更爽。。。

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <vector>#include <set>#define LL long long#define db puts("BEGIN");#define de puts("END");#define inf 2000000000LL#define Key_value ch[ch[root][1]][0]  using namespace std;const int N=100015;set<int>s;int n,q,a[N],b[N];struct Splay_tree{      LL sum[N],ans[N];    int size[N],pre[N],val[N],tot;      int ch[N][2],tot1,root,s[N],tot2;        //debug部分copy from hh      void Treaval(int x) {          if(x) {              Treaval(ch[x][0]);              printf("%2d ",val[x]);              Treaval(ch[x][1]);          }      }      void debug() {Treaval(root);puts("");}      //以上Debug      inline void NewNode(int &r,int k,int father){          if(tot2) r=s[--tot2];        else r=++tot1;          ch[r][0]=ch[r][1]=0;         sum[r]=k;        ans[r]=0LL;          pre[r]=father;          size[r]=1;          val[r]=k;      }      inline void Push_Up(int x){          if(x==0) return ;          int l=ch[x][0],r=ch[x][1];          size[x]=size[l]+size[r]+1;          sum[x]=sum[l]+sum[r]+val[x];        ans[x]=(LL)ans[l]+ans[r]-(LL)sum[l]*size[r]+(LL)sum[r]*size[l]+(LL)val[x]*(size[l]-size[r])-sum[l]+sum[r];    }      inline void Bulid(int &r,int L,int R,int father){          if(L>R)              return ;          int mid=(L+R)/2;          NewNode(r,a[mid],father);          Bulid(ch[r][0],L,mid-1,r);          Bulid(ch[r][1],mid+1,R,r);          Push_Up(r);      }      inline void Init(){          tot=tot1=tot2=root=0;          NewNode(root,-inf,0);          NewNode(ch[root][1],inf,root);          Bulid(Key_value,1,n,ch[root][1]);          Push_Up(ch[root][1]);          Push_Up(root);      }      inline void Rotate(int x,int kind){          int y=pre[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);      }      inline void Splay(int r,int goal){          while(pre[r]!=goal){              if(pre[pre[r]]==goal)                  Rotate(r,ch[pre[r]][0]==r);              else{                  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;      }      inline void RotateTo(int k, int goal) {          int x=root;          while(k!=size[ch[x][0]]+1){              if (k<=size[ch[x][0]]){                  x=ch[x][0];              }else{                  k-=(size[ch[x][0]]+1);                  x=ch[x][1];              }          }          Splay(x,goal);      }      inline int Get_Kth(int r,int k){          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);      }    inline int find(int r,int num){        if(val[r]==num) return r;        else if(val[r]<num) return find(ch[r][1],num);        else return find(ch[r][0],num);    }     inline int Insert(int pos,int k){          tot++;         RotateTo(pos,0);          RotateTo(pos+1,root);          NewNode(Key_value,k,ch[root][1]);          Push_Up(ch[root][1]);          Push_Up(root);          return Key_value;      }      inline void Delete(int r){          tot--;           Splay(r,0);          int pos=size[ch[r][0]];         RotateTo(pos,0);          RotateTo(pos+2,root);          s[tot2++]=Key_value;          Key_value=0;          Push_Up(ch[root][1]);          Push_Up(root);      }     inline void add(int r,int num,int pos){        if(num<=val[r]){            if(ch[r][0]==0)                Insert(pos,num);            else                add(ch[r][0],num,pos);        }        else{            if(ch[r][1]==0)                Insert(pos+1+size[ch[r][0]],num);            else                 add(ch[r][1],num,pos+size[ch[r][0]]+1);        }    }    inline void InOrder(int r){          if(r==0)              return;          InOrder(ch[r][0]);          printf("%d ",val[r]);          InOrder(ch[r][1]);      }      inline void Print(){          RotateTo(1,0);          RotateTo(tot+2,root);          InOrder(Key_value);          printf("\n");      }  }splay;  int main(){    //freopen("input.txt","r",stdin);    scanf("%d",&n);    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);        b[i]=a[i];        s.insert(a[i]);    }    s.insert(inf);s.insert(-inf);    sort(a+1,a+1+n);    splay.Init();    scanf("%d",&q);    set<int>::iterator it;    while(q--){        int k,l,r;        scanf("%d%d%d",&k,&l,&r);        if(k==1){            it=s.lower_bound(b[l]);            splay.Delete(splay.find(splay.root,*it));            s.erase(it);            b[l]+=r;            s.insert(b[l]);            splay.add(splay.root,b[l],0);        }        else{            it=s.lower_bound(l);it--;            splay.Splay(splay.find(splay.root,*it),0);            it=s.upper_bound(r);            splay.Splay(splay.find(splay.root,*it),splay.root);              printf("%I64d\n",splay.ans[splay.ch[splay.ch[splay.root][1]][0]]);        }    }    return 0;}


原创粉丝点击