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 } 

 

 

posted @ 2013-02-23 10:15  proverbs  阅读(1106)  评论(0编辑  收藏  举报