• HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动


      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436

      树状数组做法<猛戳>

      Splay tree的经典题目,有删除和移动操作。首先要离散化各个点,而且对于没有区间还要缩点。对于Top操作,先把目标节点删除,然后移到最左端。Query操作,Splay(tar,0),然后直接访问size。对于Rank操作,通过size产找即可。注意,在每次更新后,都要把处理过的节点都要Splay(tar,0)才能保证复杂度为O(log n),因为这样才能方便下次的访问,因为这个TLE了一个下午+一个晚上。。。。Splay()操作太神了。。

      1 //STATUS:C++_AC_187MS_4196KB
      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<<1],ch[N<<1][2];  //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
     59 int sz[N<<1],st[N];   //子树规模,内存池
     60 int root,tot,top;   //根节点,根节点数量,内存池容量
     61 //题目特定数据
     62 int op[N],cnt[N<<1],s[N<<1],e[N<<1];
     63 int num[N],p[N];
     64 int T,n,m,up;
     65 //debug部分copy from hh
     66 void Treaval(int x) {
     67     if(x) {
     68         Treaval(ch[x][0]);
     69         printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d
    ",x,ch[x][0],ch[x][1],pre[x],sz[x]);
     70         Treaval(ch[x][1]);
     71     }
     72 }
     73 void debug() {printf("%d
    ",root);Treaval(root);}
     74 //以上Debug
     75 //新建一个结点
     76 void NewNode(int &x,int fa,int k,int size)
     77 {
     78  //   if(top)x=st[--top];
     79  //   else x=++tot;
     80     x=k;
     81     pre[x]=fa;
     82     sz[x]=cnt[x]=size;
     83     ch[x][0]=ch[x][1]=0;  //左右孩子为空
     84 }
     85 
     86 inline void Push_Up(int x)
     87 {
     88     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
     89 }
     90 //旋转,kind为1为右旋,kind为0为左旋
     91 void Rotate(int x,int kind)
     92 {
     93     int y=pre[x],z=pre[y];
     94     //类似SBT,要把其中一个分支先给父节点
     95     ch[y][!kind]=ch[x][kind];
     96     pre[ch[x][kind]]=y;
     97     //如果父节点不是根结点,则要和父节点的父节点连接起来
     98     if(z)ch[z][ch[z][1]==y]=x;
     99     pre[x]=z;
    100     ch[x][kind]=y;
    101     pre[y]=x;
    102     Push_Up(y);  //维护y结点,不要维护x节点,x节点会再次Push_Down,最后维护一下x节点即可
    103 }
    104 //Splay调整,将根为r的子树调整为goal
    105 void Splay(int x,int goal)
    106 {
    107     int y,z,kind;
    108     while(pre[x]!=goal){
    109         //父节点即是目标位置,goal为0表示,父节点就是根结点
    110         y=pre[x];
    111         if(pre[y]==goal){
    112             Rotate(x,ch[y][0]==x);
    113         }
    114         else {
    115             kind=ch[pre[y]][0]==y;
    116             //两个方向不同,则先左旋再右旋
    117             if(ch[y][kind]==x){
    118                 Rotate(x,!kind);
    119                 Rotate(x,kind);
    120             }
    121             //两个方向相同,相同方向连续两次
    122             else {
    123                 Rotate(y,kind);
    124                 Rotate(x,kind);
    125             }
    126         }
    127     }
    128     //更新根结点
    129     Push_Up(x);
    130     if(goal==0)root=x;
    131 }
    132 
    133 int Get_Min(int x)
    134 {
    135     while(ch[x][0])x=ch[x][0];
    136     return x;
    137 }
    138 //建树,中间结点先建立,然后分别对区间两端在左右子树建立
    139 void BuildTree(int &x,int l,int r,int fa)
    140 {
    141     if(l>r)return;
    142     int mid=(l+r)>>1;
    143     NewNode(x,fa,mid,e[mid]-s[mid]+1);
    144     BuildTree(ch[x][0],l,mid-1,x);
    145     BuildTree(ch[x][1],mid+1,r,x);
    146     Push_Up(x);
    147 }
    148 
    149 void Init()
    150 {
    151     root=tot=top=0;
    152     ch[0][0]=ch[0][1]=pre[0]=sz[0]=cnt[0]=0;
    153 
    154     int i,t,k;
    155     char ss[8];
    156     p[0]=0,t=1;
    157     for(i=1;i<=m;i++){
    158         scanf("%s%d",ss,&num[i]);
    159         op[i]=ss[0]=='T'?1:ss[0]=='Q'?2:0;
    160         if(op[i])p[t++]=num[i];
    161     }
    162     sort(p,p+t);
    163     for(k=1,i=2;i<t;i++)
    164         if(p[i]!=p[k])p[++k]=p[i];
    165     for(i=1,up=0;i<=k;i++){
    166         if(p[i]-p[i-1]>1){
    167             s[++up]=p[i-1]+1;
    168             e[up]=p[i]-1;
    169         }
    170         s[++up]=p[i];
    171         e[up]=p[i];
    172     }
    173     if(e[up]!=n){
    174         ++up;
    175         s[up]=e[up-1]+1;
    176         e[up]=n;
    177     }
    178     BuildTree(root,1,up,0);
    179 }
    180 //删除编号为x的节点
    181 void Delete(int x)
    182 {
    183     int y=pre[x],s;
    184     if(sz[x]==cnt[x]){
    185         ch[y][ch[y][1]==x]=0;
    186         s=y;
    187     }
    188     else if(ch[x][0]==0 || ch[x][1]==0){
    189         s=ch[x][0]?ch[x][0]:ch[x][1];
    190         if(y)ch[y][ch[y][1]==x]=s;
    191         pre[s]=y;
    192     }
    193     else {
    194         s=Get_Min(ch[x][1]);
    195         Splay(s,x);
    196         if(ch[x][0]){
    197             ch[s][0]=ch[x][0];
    198             pre[ch[x][0]]=s;
    199         }
    200         pre[s]=y;
    201         if(y)ch[y][ch[y][1]==x]=s;
    202     }
    203     if(y==0)root=s;
    204     Splay(s,0);
    205 }
    206 
    207 void Top(int tar)
    208 {
    209     if(sz[root]==cnt[root])return;
    210     Delete(tar);
    211     int x=Get_Min(root);
    212     ch[x][0]=tar;
    213     pre[tar]=x;
    214     sz[tar]=cnt[tar];
    215     ch[tar][0]=ch[tar][1]=0;
    216     Splay(tar,0);
    217 }
    218 
    219 int Query(int tar)
    220 {
    221     Splay(tar,0);
    222     return sz[ch[root][0]]+cnt[tar];
    223 }
    224 
    225 int Rank(int k)
    226 {
    227     int x=root;
    228     while(1){
    229         if(k>sz[ch[x][0]] && k<=sz[ch[x][0]]+cnt[x]){
    230             k-=sz[ch[x][0]];
    231             break;
    232         }
    233         else if(k<=sz[ch[x][0]])
    234             x=ch[x][0];
    235         else {
    236             k-=sz[ch[x][0]]+cnt[x];
    237             x=ch[x][1];
    238         }
    239     }
    240     return s[x]+k-1;
    241 }
    242 
    243 int binary(int l,int r,int tar)
    244 {
    245     int mid;
    246     while(l<r){
    247         mid=(l+r)>>1;
    248         if(e[mid]<tar)l=mid+1;
    249         else if(s[mid]>tar)r=mid;
    250         else return mid;
    251     }
    252     return -1;
    253 }
    254 
    255 int main()
    256 {
    257  //   freopen("in.txt","r",stdin);
    258     int i,j,ca=1,tar;
    259     scanf("%d",&T);
    260     while(T--)
    261     {
    262         scanf("%d%d",&n,&m);
    263         Init();
    264         printf("Case %d:
    ",ca++);
    265         for(i=1;i<=m;i++){
    266             if(op[i]){
    267                 tar=binary(1,up+1,num[i]);
    268                 if(op[i]==1)Top(tar);
    269                 else printf("%d
    ",Query(tar));
    270             }
    271             else printf("%d
    ",Rank(num[i]));
    272         }
    273     }
    274     return 0;
    275 }
  • 相关阅读:
    MVC4新功能...压缩和合并js文件和样式文件
    如何将sqlserver表中的数据导出sql语句或生成insert into语句 [转]
    利用svn自动同步更新到网站服务器 -- 网摘
    找不到方法: Int32 System.Environment.get_CurrentManagedThreadId() .
    C# .NET ASP.NET 其中关系你了解多少
    SQL语句分享[不定期更新]
    云平台概念学习
    【转】用户画像和用户档案的区别
    【转】外行杂谈论—聊聊看板 vs 大屏的区别
    【转】从信息、能量、物质的角度揭示生命真相
  • 原文地址:https://www.cnblogs.com/zhsl/p/3213440.html
Copyright © 2020-2023  润新知