HDU3726---Graph and Queries 离线处理+Treap

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

题意:n个点m条边的一张无向图,每个点有一个权值, 有3中操作。

D X 删除第X条边

Q X K 计算与X点相连所有点中第k大的权值

C X V把X的权值改为 V

输出 Q次询问的平均值

大白上的例题, 离线处理,把所有操作 反过来处理,,这样删边变成了 加边,,瞬间好处理多了。。细节也有很多。

  1 #include <set>

  2 #include <map>

  3 #include <cmath>

  4 #include <ctime>

  5 #include <queue>

  6 #include <stack>

  7 #include <cstdio>

  8 #include <string>

  9 #include <vector>

 10 #include <cstdlib>

 11 #include <cstring>

 12 #include <iostream>

 13 #include <algorithm>

 14 using namespace std;

 15 typedef unsigned long long ull;

 16 typedef long long ll;

 17 const int inf = 0x3f3f3f3f;

 18 const double eps = 1e-8;

 19 const int maxn = 2e4+10;

 20 int n, m, val[maxn];

 21 int pa[maxn];

 22 void init()

 23 {

 24     for (int i = 0; i <= n; i++)

 25     {

 26         pa[i] = i;

 27     }

 28 }

 29 int find(int x)

 30 {

 31     return pa[x] = (pa[x] == x ? x : find(pa[x]));

 32 }

 33 struct Node

 34 {

 35     Node* ch[2];

 36     int key, r, siz;

 37     Node (int x)

 38     {

 39         key = x;

 40         siz = 1;

 41         ch[0] = ch[1] = NULL;

 42         r = rand();

 43     }

 44     bool operator < (const Node &rhs)const

 45     {

 46         return r < rhs.r;

 47     }

 48     int cmp(int x)

 49     {

 50         if (x == key)

 51             return -1;

 52         return x < key ? 0 : 1;

 53     }

 54     void maintain()

 55     {

 56         siz = 1;

 57         if (ch[0] != NULL)

 58             siz += ch[0] -> siz;

 59         if (ch[1] != NULL)

 60             siz += ch[1] -> siz;

 61     }

 62 };

 63 void rotate(Node* &root, int d)

 64 {

 65     Node* tmp = root -> ch[d^1];

 66     root -> ch[d^1] = tmp -> ch[d];

 67     tmp -> ch[d] = root;

 68     root -> maintain();

 69     tmp -> maintain();

 70     root = tmp;

 71 }

 72 void insert(Node* &root, int x)

 73 {

 74     if (root == NULL)

 75         root = new Node (x);

 76     else

 77     {

 78         int d = x < root -> key ? 0 : 1;

 79         insert (root ->ch[d], x);

 80         if (root -> ch[d] -> r > root -> r)

 81             rotate(root, d^1);

 82 

 83     }

 84     root -> maintain();

 85 }

 86 void dele(Node* &root, int x)

 87 {

 88     int d = root -> cmp(x);

 89     if (d == -1)

 90     {

 91         Node* tmp = root;

 92         if (root -> ch[0] != NULL && root -> ch[1] != NULL)

 93         {

 94             int d1 = (root -> ch[0] -> r > root -> ch[1] -> r ? 0 : 1);

 95             rotate(root, d1^1);

 96             dele(root -> ch[d1^1], x);

 97         }

 98         else

 99         {

100             if (root -> ch[0] == NULL)

101                 root = root -> ch[1];

102             else

103                 root = root -> ch[0];

104             delete tmp;

105         }

106     }

107     else

108         dele(root->ch[d], x);

109     if (root != NULL)

110         root -> maintain();

111 }

112 int Get_kth(Node* root, int k)

113 {

114     if (root == NULL || k <= 0 || root -> siz < k)

115         return 0;

116     int s = root -> ch[1] == NULL ? 0 : root -> ch[1] -> siz;

117     if (s + 1 == k)

118         return root -> key;

119     if (s + 1 > k)

120         return Get_kth(root -> ch[1], k);

121     else

122         return Get_kth(root -> ch[0], k-s-1);

123 

124 }

125 Node* root[maxn];

126 void merge_tree(Node* &src, Node* &fa)

127 {

128     if (src -> ch[0] != NULL)

129         merge_tree(src -> ch[0], fa);

130     if (src -> ch[1] != NULL)

131         merge_tree(src -> ch[1], fa);

132     insert(fa, src -> key);

133     delete src;

134     src = NULL;

135 }

136 void remove_tree(Node* &root)

137 {

138     if (root -> ch[0] != NULL)

139         remove_tree(root -> ch[0]);

140     if (root -> ch[1] != NULL)

141         remove_tree(root -> ch[1]);

142     delete root;

143     root = NULL;

144 }

145 struct

146 {

147     int x, y;

148     bool is_del;

149 } e[3 * maxn];

150 struct

151 {

152     int type, x, p;

153 } Q[maxn*25];

154 void add_edge(int idx)

155 {

156     int fx = find(e[idx].x);

157     int fy = find(e[idx].y);

158     if (fx != fy)

159     {

160         if (root[fx] -> siz > root[fy] -> siz)

161         {

162             pa[fy] = fx;

163             merge_tree(root[fy], root[fx]);

164         }

165         else

166         {

167             pa[fx] = fy;

168             merge_tree(root[fx], root[fy]);

169 

170         }

171     }

172 

173 }

174 int main(void)

175 {

176 #ifndef ONLINE_JUDGE

177     freopen("in.txt","r",stdin);

178 #endif

179     int cas = 1;

180     while (~ scanf ("%d%d",&n, &m))

181     {

182         if (n == 0 && m == 0)

183             break;

184         for (int i = 0; i < n; i++)

185         {

186             scanf ("%d", val + 1 + i);

187         }

188         for (int i = 1; i <= m; i++)

189         {

190             scanf ("%d%d", &e[i].x, &e[i].y);

191             e[i].is_del = false;

192         }

193         char op[5];

194         int tot = 0;

195         while (scanf ("%s",op) && op[0] != 'E')

196         {

197             if (op[0] == 'D')

198             {

199                 scanf ("%d", &Q[tot].x);

200                 Q[tot++].type = 0;

201                 e[Q[tot-1].x].is_del = true;

202             }

203             if (op[0] == 'Q')

204             {

205                 scanf ("%d%d", &Q[tot].x, &Q[tot].p);

206                 Q[tot++].type = 1;

207             }

208             if (op[0] == 'C')

209             {

210                 int v;

211                 scanf ("%d%d", &Q[tot].x, &v);

212                 Q[tot].p = val[Q[tot].x];

213                 val[Q[tot].x] = v;

214                 Q[tot++].type = 2;

215             }

216         }

217         init();

218         for (int i = 0; i < n; i++)

219         {

220             if (root[i+1] != NULL)

221                 remove_tree(root[i+1]);

222             root[i+1] = new Node (val[i+1]);

223         }

224         for (int i = 0; i < m; i++)

225         {

226             if (e[i+1].is_del == false)

227                 add_edge(i+1);

228         }

229         ll ans1 = 0, ans2 = 0;

230         for (int i = tot - 1; i >= 0; i--)

231         {

232             if (Q[i].type == 0)

233             {

234                 add_edge(Q[i].x);

235             }

236             if (Q[i].type == 1)

237             {

238                 ans1 += Get_kth(root[find(Q[i].x)], Q[i].p);

239                 ans2 ++;

240             }

241             if (Q[i].type == 2)

242             {

243                int father = find(Q[i].x);

244                 dele (root[father], val[Q[i].x]);

245                 insert (root[father], Q[i].p);

246                 val[Q[i].x] = Q[i].p;

247             }

248         }

249         printf("Case %d: %.6f\n", cas++, 1.0*ans1 / ans2);

250     }

251     return 0;

252 }

 

你可能感兴趣的:(Graph)