[BZOJ 3123]森林

这题和 COT1 一定有 JQ 喵~

 

线段树的启发式合并,每次要连接两个点时就对比较小的那棵树暴力 DFS 一边

然后均摊时间依旧是 logn 的,均摊真是世界上最邪恶的东西了……

 

然后这题的数据是要卖萌么?!
testcase 的存在意义是被阿卡林噎掉了么?!

 

  1 #include <cstdio>

  2 #include <cstring>

  3 #include <algorithm>

  4 const int sizeOfPoint=100001;

  5 const int sizeOfEdge=200002;

  6 const int sizeOfNode=20000002;

  7 

  8 inline int lg(int);

  9 inline void swap(int & , int & );

 10 inline char getch();

 11 inline int getint();

 12 inline void putint(int);

 13 

 14 struct edge {int point; edge * next;};

 15 edge memory_edge[sizeOfEdge], * port_edge=memory_edge;

 16 inline edge * newedge(int, edge * );

 17 inline void link(int, int);

 18 

 19 struct node {int c; node * l , * r; inline node();};

 20 node * null=new node();

 21 node memory_node[sizeOfNode], * port_node=memory_node;

 22 inline node * newnode(node * =null);

 23 node * insert(node * , int, int, int);

 24 

 25 int b[sizeOfPoint], s[sizeOfPoint];

 26 int find(int);

 27 inline void merge(int, int);

 28 

 29 int testcase;

 30 int N, M, T, U;

 31 int p[sizeOfPoint], q[sizeOfPoint];

 32 int f[sizeOfPoint], d[sizeOfPoint], a[32][sizeOfPoint];

 33 edge * e[sizeOfPoint];

 34 node * t[sizeOfPoint];

 35 inline void clear();

 36 inline bool cmp(int, int);

 37 inline void discretization();

 38 void dfs(int);

 39 inline int lca(int, int);

 40 inline int query(int, int, int);

 41 

 42 int main()

 43 {

 44     int lastans=0;

 45 

 46     testcase=getint();

 47     for (testcase=1;testcase;testcase--)

 48     {

 49         N=getint(), M=getint(), T=getint();

 50         clear();

 51         for (int i=1;i<=N;i++)

 52             p[i]=getint();

 53         for (int i=1;i<=M;i++)

 54         {

 55             int u=getint(), v=getint();

 56             link(u, v);

 57         }

 58         discretization();

 59 

 60         for (int i=1;i<=N;i++) if (f[i]==-1)

 61         {

 62             f[i]=0; d[i]=0;

 63             dfs(i);

 64         }

 65 

 66         for (int i=1;i<=T;i++)

 67         {

 68             char c=getch(); int x=getint()^lastans, y=getint()^lastans;

 69             if (c=='Q')

 70             {

 71                 int k=getint()^lastans;

 72                 lastans=query(x, y, k);

 73                 putint(lastans);

 74             }

 75             else

 76             {

 77                 int bx=find(x), by=find(y);

 78                 if (bx==by) continue;

 79                 if (s[bx]<s[by]) swap(x, y);

 80                 link(x, y);

 81                 f[y]=x; d[y]=d[x]+1;

 82                 dfs(y);

 83             }

 84         }

 85     }

 86 

 87     return 0;

 88 }

 89 

 90 inline int lg(int x)

 91 {

 92     return 31-__builtin_clz(x);

 93 }

 94 inline void swap(int & x, int & y)

 95 {

 96     int z=x;

 97         x=y;

 98         y=z;

 99 }

100 inline char getch()

101 {

102     register char ch;

103     do ch=getchar(); while (ch!='L' && ch!='Q');

104     return ch;

105 }

106 inline int getint()

107 {

108     register int num=0;

109     register char ch=0, last;

110     do last=ch, ch=getchar(); while (ch<'0' || ch>'9');

111     do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');

112     if (last=='-') num=-num;

113     return num;

114 }

115 inline void putint(int num)

116 {

117     char stack[11];

118     register int top=0;

119     if (num==0) stack[top=1]='0';

120     if (num<0) putchar('-'), num=-num;

121     for ( ;num;num/=10) stack[++top]=num%10+'0';

122     for ( ;top;top--) putchar(stack[top]);

123     putchar('\n');

124 }

125 

126 inline edge * newedge(int point, edge * next)

127 {

128     edge * ret=port_edge++;

129     ret->point=point; ret->next=next;

130     return ret;

131 }

132 inline void link(int u, int v)

133 {

134     e[u]=newedge(v, e[u]);

135     e[v]=newedge(u, e[v]);

136     merge(u, v);

137 }

138 

139 inline node::node()

140 {

141     this->c=0;

142     this->l=this;

143     this->r=this;

144 }

145 inline node * newnode(node * t)

146 {

147     node * newt=port_node++;

148     *newt=*t;

149     return newt;

150 }

151 node * insert(node * t, int l, int r, int k)

152 {

153     t=newnode(t);

154     t->c++;

155     if (l==r) return t;

156 

157     int m=(l+r)>>1;

158     if (k<=m) t->l=insert(t->l, l, m, k);

159     else t->r=insert(t->r, m+1, r, k);

160     return t;

161 }

162 

163 int find(int u)

164 {

165     return !b[u]?u:b[u]=find(b[u]);

166 }

167 inline void merge(int u, int v)

168 {

169     u=find(u); v=find(v);

170     b[v]=u; s[u]+=s[v];

171 }

172 

173 inline void clear()

174 {

175     port_edge=memory_edge;

176     memset(e, 0, sizeof(e));

177     port_node=memory_node;

178     for (int i=0;i<=N;i++) t[i]=null;

179     memset(f, -1, sizeof(f));

180     memset(d, -1, sizeof(d));

181     memset(b, 0, sizeof(b));

182     memset(a, 0, sizeof(a));

183     for (int i=1;i<=N;i++) s[i]=1;

184 }

185 inline bool cmp(int a, int b)

186 {

187     return p[a]<p[b];

188 }

189 inline void discretization()

190 {

191     static int k[sizeOfPoint];

192 

193     for (int i=1;i<=N;i++) k[i]=i;

194     std::sort(k+1, k+N+1, cmp);

195 

196     q[U=1]=p[k[1]]; p[k[1]]=1;

197     for (int i=2;i<=N;i++)

198     {

199         if (p[k[i]]>q[U]) q[++U]=p[k[i]];

200         p[k[i]]=U;

201     }

202 }

203 void dfs(int u)

204 {

205     t[u]=insert(t[f[u]], 1, U, p[u]);

206     if (d[u]>0)

207     {

208         int lim=lg(d[u]);

209         a[0][u]=f[u];

210         for (int i=1;i<=lim;i++)

211             a[i][u]=a[i-1][a[i-1][u]];

212         for (int i=lim+1;i<31;i++)

213             a[i][u]=0;

214     }

215 

216     for (edge * i=e[u];i;i=i->next) if (i->point!=f[u])

217     {

218         f[i->point]=u;

219         d[i->point]=d[u]+1;

220         dfs(i->point);

221     }

222 }

223 inline int lca(int u, int v)

224 {

225     if (d[u]<d[v]) swap(u, v);

226     while (int dist=d[u]-d[v]) u=a[__builtin_ctz(dist)][u];

227     if (u==v) return u;

228     for (int i=31;i>=0;i--)

229         if (a[i][u]!=a[i][v])

230             u=a[i][u],

231             v=a[i][v];

232     return f[u];

233 }

234 inline int query(int a, int b, int k)

235 {

236     int c=lca(a, b), d=f[c];

237     node * ta=t[a], * tb=t[b], * tc=t[c], * td=t[d];

238     int l=1, r=U, m;

239 

240     for ( ;l<r; )

241     {

242         m=(l+r)>>1;

243         if (ta->l->c+tb->l->c-tc->l->c-td->l->c>=k)

244         {

245             ta=ta->l; tb=tb->l; tc=tc->l; td=td->l;

246             r=m;

247         }

248         else

249         {

250             k-=ta->l->c+tb->l->c-tc->l->c-td->l->c;

251             ta=ta->r; tb=tb->r; tc=tc->r; td=td->r;

252             l=m+1;

253         }

254     }

255 

256     return q[l];

257 }
又 R 又 T 一时爽

 

你可能感兴趣的:(ZOJ)