zoukankan      html  css  js  c++  java
  • BZOJ 2120 树状数组套平衡树

    题解:

    每个数第一次出现时随便改成pos-n,之后改成前一次出现的位置。询问的时候查找一个区间中比左端点小的数的个数

    吐槽:

    尼玛数组越界了查了一晚上+半个下午。

    树套树这种东西真难查错!

    我多插入了很多没有用的节点,所以就慢了点,不过省代码~

    View Code
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 #include <cstdio>
      6  
      7 #define N 6000050
      8 #define INF 520131499
      9 #define CN 1000000
     10 #define lowbit(x) x&-x
     11 #define BUG system("pause");
     12 #define CA puts("ca");
     13  
     14 using namespace std;
     15  
     16 int sz[N],val[N],fa[N],son[N][2];
     17 int rc[CN+10],root[N],col[N];
     18 int cnt,num,q[N+CN];
     19 int suf[N],pre[N],jp[CN+10];
     20 int n,m;
     21 
     22 inline void prt(int x)
     23 {
     24     if(!x) return;
     25     prt(son[x][0]);
     26     printf("%d    ",val[x]);
     27     prt(son[x][1]);
     28 }
     29 
     30 inline void pushup(int x)
     31 {
     32     if(!x) return;
     33     sz[x]=sz[son[x][0]]+sz[son[x][1]]+1;
     34 }
     35  
     36 inline void link(int x,int y,int c)
     37 {
     38     fa[x]=y; son[y][c]=x;
     39 }
     40  
     41 inline void rotate(int x,int c)
     42 {
     43     int y=fa[x];
     44     link(x,fa[y],son[fa[y]][1]==y);
     45     link(son[x][!c],y,c);
     46     link(y,x,!c);
     47     pushup(y);
     48 }
     49  
     50 inline void splay(int x,int g,int &rt)
     51 {
     52     while(fa[x]!=g)
     53     {
     54         int y=fa[x];
     55         int cy=(son[fa[y]][1]==y),cx=(son[y][1]==x);
     56         if(fa[y]==g) rotate(x,cx);
     57         else
     58         {
     59             if(cx==cy) rotate(y,cy);
     60             else rotate(x,cx);
     61             rotate(x,cy);
     62         }
     63     }
     64     pushup(x);
     65     if(!g) rt=x;
     66 }
     67  
     68 inline int getnum()
     69 {
     70     if(num==0) return ++cnt;
     71     return q[num--];
     72 }
     73  
     74 inline void newnode(int y,int &x,int sp)
     75 {
     76     x=getnum();
     77     fa[x]=y; val[x]=sp; sz[x]=1;
     78     son[x][1]=son[x][0]=0;
     79 }
     80  
     81 inline int getmin(int x)
     82 {
     83     while(son[x][0]) x=son[x][0];
     84     return x;
     85 }
     86  
     87 inline int getmax(int x)
     88 {
     89     while(son[x][1]) x=son[x][1];
     90     return x;
     91 }
     92  
     93 inline int pred(int x,int sp)
     94 {
     95     int res=-INF-10,ans=x;
     96     while(x)
     97     {
     98         if(val[x]==sp) return x;
     99         else if(val[x]<sp&&val[x]>res) res=val[x],ans=x;
    100         x=son[x][val[x]<sp];
    101     }
    102     return ans;
    103 }
    104  
    105 inline int succ(int x,int sp)
    106 {
    107     int res=INF+10,ans=x;
    108     while(x)
    109     {
    110         if(val[x]==sp) return x;
    111         else if(val[x]>sp&&val[x]<res) res=val[x],ans=x;
    112         x=son[x][val[x]<sp];
    113     }
    114     return ans;
    115 }
    116 
    117 inline int query(int &rt,int sp)
    118 {
    119     int l=getmin(rt),r=succ(rt,sp);
    120     splay(l,0,rt); splay(r,l,rt);
    121     return sz[son[r][0]];
    122 }
    123  
    124 inline void insert(int &rt,int sp)
    125 {
    126     int x=rt;
    127     while(son[x][val[x]<sp]) x=son[x][val[x]<sp];
    128     newnode(x,son[x][val[x]<sp],sp);
    129     splay(son[x][val[x]<sp],0,rt);
    130 }
    131  
    132 inline void del(int &rt,int sp)
    133 {
    134     int p=pred(rt,sp-1),s=succ(rt,sp+1);
    135     splay(p,0,rt); splay(s,p,rt);
    136     
    137     q[++num]=son[s][0];
    138     son[s][0]=0;
    139     pushup(s); pushup(p);
    140 }
    141  
    142 inline int getans(int x,int sp)
    143 {
    144     int res=0;
    145     for(int i=x;i;i-=lowbit(i)) res+=query(root[i],sp);
    146     return res;
    147 }
    148  
    149 inline void updata(int x,int y)
    150 {
    151     if(y==col[x]) return;
    152     for(int i=x;i<=n;i+=lowbit(i)) del(root[i],pre[x]);//删除当前颜色的前缀 
    153     if(suf[x]<=n)
    154     {
    155         for(int i=suf[x];i<=n;i+=lowbit(i)) del(root[i],pre[suf[x]]);//删除当前颜色后缀的前缀 
    156         pre[suf[x]]=pre[x];//把当前颜色后缀的前缀改为当前颜色 
    157         if(pre[suf[x]]<=0) pre[suf[x]]=suf[x]-n;
    158         for(int i=suf[x];i<=n;i+=lowbit(i)) insert(root[i],pre[suf[x]]);//把当前颜色后缀的前缀改为当前颜色 
    159     }
    160     if(pre[x])
    161     {
    162         suf[pre[x]]=suf[x];//把当前颜色的前缀的后缀改为当前颜色的后缀 
    163         if(suf[pre[x]]>n) suf[pre[x]]=pre[x]+n;
    164     }
    165     del(rc[col[x]],x); insert(rc[y],x);//颜色splay中删除旧颜色,添加新颜色 
    166     int l=val[getmax(son[rc[y]][0])],r=val[getmin(son[rc[y]][1])];//新颜色的前缀和后缀(新) 
    167     if(l!=-INF) pre[x]=l,suf[l]=x;//前缀和当前建立关系 (新) 
    168     else pre[x]=x-n; 
    169     if(r!=INF)//存在后缀 (新) 
    170     {
    171         for(int i=r;i<=n;i+=lowbit(i)) del(root[i],pre[r]);//删除新颜色的后缀的前缀 (新) 
    172         suf[x]=r;pre[r]=x;//后缀和当前建立关系 
    173         for(int i=r;i<=n;i+=lowbit(i)) insert(root[i],pre[r]);//插入新颜色的前缀 (新) 
    174     }
    175     else suf[x]=n+x;
    176     for(int i=x;i<=n;i+=lowbit(i)) insert(root[i],pre[x]);//插入当前颜色的前缀 (新) 
    177     col[x]=y;
    178 }
    179  
    180 inline void read()
    181 {
    182     scanf("%d%d",&n,&m);
    183     for(int i=1;i<=n;i++)
    184     {
    185         scanf("%d",&col[i]);
    186         newnode(0,root[i],-INF);
    187         newnode(root[i],son[root[i]][1],INF);
    188         sz[root[i]]=2;
    189     }
    190     for(int i=1;i<=n;i++)
    191     {
    192         if(!jp[col[i]]) pre[i]=i-n;
    193         else pre[i]=jp[col[i]];
    194         jp[col[i]]=i;
    195     }
    196     for(int i=1;i<=CN;i++) jp[i]=n+1;
    197     for(int i=n;i>=1;i--)
    198     {
    199         if(jp[col[i]]==n+1) suf[i]=i+n;
    200         else suf[i]=jp[col[i]];
    201         jp[col[i]]=i;
    202     }
    203     for(int i=1;i<=CN;i++)
    204     {
    205         newnode(0,rc[i],-INF);
    206         newnode(rc[i],son[rc[i]][1],INF);
    207         sz[rc[i]]=2;
    208     }
    209 }
    210 
    211 inline void go()
    212 {
    213     for(int i=1;i<=n;i++)
    214     {
    215         for(int j=i;j<=n;j+=lowbit(j)) insert(root[j],pre[i]);
    216         insert(rc[col[i]],i);
    217     }
    218     char str[3];int x,y;
    219     while(m--)
    220     {
    221         scanf("%s%d%d",str,&x,&y);
    222         if(str[0]=='Q') printf("%d\n",getans(y,x)-getans(x-1,x));
    223         else updata(x,y);
    224     }
    225 }
    226  
    227 int main()
    228 {
    229     read(),go();
    230     return 0;
    231 }

     赠送对拍器:

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <cstdlib>
     5 #include <ctime>
     6 
     7 using namespace std;
     8 
     9 int main()
    10 {
    11     srand(time(0));
    12     while(1)
    13     {
    14         FILE *fp=fopen("3.txt","w");
    15         int n=10,m=20;
    16         fprintf(fp,"%d %d\n",n,m);
    17         for(int i=1;i<=n;i++) fprintf(fp,"%d ",rand()%6+1);
    18         fprintf(fp,"\n");
    19         for(int i=1;i<=m;i++)
    20         {
    21             int a,b,c;
    22             a=rand()&1;
    23             b=rand()%10+1;
    24             if(a)
    25             {
    26                 c=rand()%10+1;
    27                 if(b>c) swap(b,c);
    28                 fprintf(fp,"Q %d %d\n",b,c);
    29             }
    30             else
    31             {
    32                 c=rand()%6+1;
    33                 fprintf(fp,"R %d %d\n",b,c);
    34             }
    35         }
    36         fclose(fp);
    37         system("1.exe");system("2.exe");
    38         if(system("fc 1.txt 2.txt"))
    39         {
    40             puts("ca");
    41             getchar();
    42         }
    43     }
    44     return 0;
    45 } 
  • 相关阅读:
    一文搞懂字符集
    机器视觉之eVision
    PID调节
    激光切割质量主要影响因素
    155. 最小栈
    111.二叉树最小深度
    110. 平衡二叉树
    108.将有序数组转换为二叉搜索树
    107. 二叉树的层次遍历 II
    104. 二叉树的最大深度
  • 原文地址:https://www.cnblogs.com/proverbs/p/2923195.html
Copyright © 2011-2022 走看看