题解:
每个数第一次出现时随便改成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 }