zoukankan      html  css  js  c++  java
  • POJ-3468 A Simple Problem with Integers Splay Tree区间练习

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

      以前用线段树做过,现在用Splay Tree A了,向HHkuangbincxlove大牛学习了各种Splay各种操作,,,Orz。。

      Splay Tree的区间操作和线段树的操作差不多,也是保存子树的值,然后懒惰操作,在Rotate()最后维护节点信息的时候,只要Push_Up(y)的,因为x还需要网上旋转到根节点,最后更新下就可以了,并且在下一次Rotate()的时候,还会Push_Down(x)的信息,因此不能Push_Up(x)。

      1 //STATUS:C++_AC_3407MS_3696KB
      2 #include <functional>
      3 #include <algorithm>
      4 #include <iostream>
      5 //#include <ext/rope>
      6 #include <fstream>
      7 #include <sstream>
      8 #include <iomanip>
      9 #include <numeric>
     10 #include <cstring>
     11 #include <cassert>
     12 #include <cstdio>
     13 #include <string>
     14 #include <vector>
     15 #include <bitset>
     16 #include <queue>
     17 #include <stack>
     18 #include <cmath>
     19 #include <ctime>
     20 #include <list>
     21 #include <set>
     22 #include <map>
     23 using namespace std;
     24 //using namespace __gnu_cxx;
     25 //define
     26 #define pii pair<int,int>
     27 #define mem(a,b) memset(a,b,sizeof(a))
     28 #define lson l,mid,rt<<1
     29 #define rson mid+1,r,rt<<1|1
     30 #define PI acos(-1.0)
     31 //typedef
     32 typedef __int64 LL;
     33 typedef unsigned __int64 ULL;
     34 //const
     35 const int N=100010;
     36 const int INF=0x3f3f3f3f;
     37 const int MOD=100000,STA=8000010;
     38 const LL LNF=1LL<<60;
     39 const double EPS=1e-8;
     40 const double OO=1e15;
     41 const int dx[4]={-1,0,1,0};
     42 const int dy[4]={0,1,0,-1};
     43 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
     44 //Daily Use ...
     45 inline int sign(double x){return (x>EPS)-(x<-EPS);}
     46 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
     47 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
     48 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
     49 template<class T> inline T Min(T a,T b){return a<b?a:b;}
     50 template<class T> inline T Max(T a,T b){return a>b?a:b;}
     51 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
     52 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
     53 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
     54 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
     55 //End
     56 
     57 #define Key_value ch[ch[root][1]][0]
     58 int pre[N],key[N],ch[N][2];  //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
     59 int sz[N],st[N];   //子树规模,内存池
     60 int root,tot,top;   //根节点,根节点数量,内存池容量
     61 //题目特定数据
     62 int num[N];
     63 int val[N];
     64 int add[N];
     65 LL sum[N];
     66 int n,m;
     67 //debug部分copy from hh
     68 void Treaval(int x) {
     69     if(x) {
     70         Treaval(ch[x][0]);
     71         printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d , sum = %2d 
    ",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x],sum[x]);
     72         Treaval(ch[x][1]);
     73     }
     74 }
     75 void debug() {printf("%d
    ",root);Treaval(root);}
     76 //以上Debug
     77 //新建一个结点
     78 void NewNode(int &x,int fa,int k)
     79 {
     80     if(top)x=st[--top];
     81     else x=++tot;
     82     pre[x]=fa;
     83     sz[x]=1;
     84     val[x]=k;
     85     add[x]=0;
     86     sum[x]=k;
     87     ch[x][0]=ch[x][1]=0;  //左右孩子为空
     88 }
     89 
     90 void Push_Up(int x)
     91 {
     92     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
     93     sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
     94 }
     95 
     96 void Push_Down(int x)
     97 {
     98     if(add[x]){
     99         val[x]+=add[x];
    100         add[ch[x][0]]+=add[x];
    101         add[ch[x][1]]+=add[x];
    102         sum[ch[x][0]]+=(LL)add[x]*sz[ch[x][0]];
    103         sum[ch[x][1]]+=(LL)add[x]*sz[ch[x][1]];
    104         add[x]=0;
    105     }
    106 }
    107 
    108 //旋转,kind为1为右旋,kind为0为左旋
    109 void Rotate(int x,int kind)
    110 {
    111     int y=pre[x],z=pre[y];
    112     Push_Down(y);
    113     Push_Down(x);  //先把y的标记向下传递,再把x的标记往下传递
    114     //类似SBT,要把其中一个分支先给父节点
    115     ch[y][!kind]=ch[x][kind];
    116     pre[ch[x][kind]]=y;
    117     //如果父节点不是根结点,则要和父节点的父节点连接起来
    118     if(z)ch[z][ch[z][1]==y]=x;
    119     pre[x]=z;
    120     ch[x][kind]=y;
    121     pre[y]=x;
    122     Push_Up(y);  //维护y结点,不要维护x节点,x节点会再次Push_Down,最后维护一下x节点即可
    123 }
    124 //Splay调整,将根为r的子树调整为goal
    125 void Splay(int x,int goal)
    126 {
    127     int y,kind;
    128     while(pre[x]!=goal){
    129         //父节点即是目标位置,goal为0表示,父节点就是根结点
    130         y=pre[x];
    131         if(pre[y]==goal){
    132             Rotate(x,ch[y][0]==x);
    133         }
    134         else {
    135             kind=ch[pre[y]][0]==y;
    136             //两个方向不同,则先左旋再右旋
    137             if(ch[y][kind]==x){
    138                 Rotate(x,!kind);
    139                 Rotate(x,kind);
    140             }
    141             //两个方向相同,相同方向连续两次
    142             else {
    143                 Rotate(y,kind);
    144                 Rotate(x,kind);
    145             }
    146         }
    147     }
    148     //更新根结点
    149     Push_Up(x);
    150     if(goal==0)root=x;
    151 }
    152 
    153 void RotateTo(int k,int goal)
    154 {
    155     int x=root;
    156     Push_Down(x);
    157     while(sz[ch[x][0]]!=k){
    158         if(sz[ch[x][0]]>k)
    159             x=ch[x][0];
    160         else {
    161             k-=sz[ch[x][0]]+1;
    162             x=ch[x][1];
    163         }
    164         Push_Down(x);
    165     }
    166     Splay(x,goal);
    167 }
    168 
    169 int Insert(int k)
    170 {
    171     int x=root;
    172     while(ch[x][k>key[x]]){
    173         //不重复插入
    174         if(key[x]==k){
    175             Splay(x,0);
    176             return 0;
    177         }
    178         x=ch[x][k>key[x]];
    179     }
    180     NewNode(ch[x][k>key[x]],x,k);
    181     //将新插入的结点更新至根结点
    182     Splay(ch[x][k>key[x]],0);
    183     return 1;
    184 }
    185 //找前驱,即左子树的最右结点
    186 int Get_Pre(int x)
    187 {
    188     if(!ch[x][0])return -INF;
    189     x=ch[x][0];
    190     while(ch[x][1])x=ch[x][1];
    191     return key[x];
    192 }
    193 //找后继,即右子树的最左结点
    194 int Get_Suf(int x)
    195 {
    196     if(!ch[x][1])return INF;
    197     x=ch[x][1];
    198     while(ch[x][0])x=ch[x][0];
    199     return key[x];
    200 }
    201 //建树,中间结点先建立,然后分别对区间两端在左右子树建立  
    202 void BuildTree(int &x,int l,int r,int fa)
    203 {
    204     if(l>r)return;
    205     int mid=(l+r)>>1;
    206     NewNode(x,fa,num[mid]);
    207     BuildTree(ch[x][0],l,mid-1,x);
    208     BuildTree(ch[x][1],mid+1,r,x);
    209     Push_Up(x);
    210 }
    211 
    212 void Init()
    213 {
    214     ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
    215     add[0]=sum[0]=0;
    216     root=top=tot=0;
    217     NewNode(root,0,-1); 
    218     NewNode(ch[root][1],root,-1);     //头尾各加入一个空位
    219     sz[root]=2;
    220 
    221     for(int i=0;i<n;i++)
    222         scanf("%d",&num[i]);
    223     BuildTree(Key_value,0,n-1,ch[root][1]);    //让所有数据夹在两个-1之间  
    224     Push_Up(ch[root][1]);
    225     Push_Up(root);
    226 }
    227 
    228 void Update(int a,int b,int c)
    229 {
    230     RotateTo(a-1,0);
    231     RotateTo(b+1,root);
    232     add[Key_value]+=c;
    233     sum[Key_value]+=sz[Key_value]*c;
    234 }
    235 
    236 LL Query(int a,int b)
    237 {
    238     RotateTo(a-1,0);
    239     RotateTo(b+1,root);
    240     return sum[Key_value];
    241 }
    242 
    243 int main()
    244 {
    245  //   freopen("in.txt","r",stdin);
    246     int i,j,a,b,c;
    247     char op[2];
    248     while(~scanf("%d%d",&n,&m))
    249     {
    250         Init();
    251         while(m--){
    252             scanf("%s",op);
    253             if(op[0]=='Q'){
    254                 scanf("%d%d",&a,&b);
    255                 printf("%I64d
    ",Query(a,b));
    256             }
    257             else {
    258                 scanf("%d%d%d",&a,&b,&c);
    259                 Update(a,b,c);
    260             }
    261         }
    262     }
    263     return 0;
    264 }
  • 相关阅读:
    models F Q查询
    Django models 多对多 操作
    Cookies与session的区别
    Form表单验证
    图片上传
    Django进阶
    sql 单个字段去重查询 distinc 和 group by的效率问题
    Django知识点整理
    Web应用请求和响应 HTTP相关
    Django中的几种重定向方式
  • 原文地址:https://www.cnblogs.com/zhsl/p/3199752.html
Copyright © 2011-2022 走看看