2013多校训练赛第一场 总结

http://acm.hdu.edu.cn/listproblem.php?vol=37

hdu 4600~4610 2013HDU多校训练第一场

  这次的组队训练好没状态,居然敲几题水题都搞了2个多种。最后我们队做出了4题,排在41名。

不太想写东西,直接上题解了:

Problem - 4604

  这题做法其实还没想到,不过写出了一个能过目前所有数据的代码(比赛的时候数据更水,几乎算不出正确答案的代码都能过):

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <map>
 6 
 7 using namespace std;
 8 
 9 const int N = 111111;
10 
11 int rec[N], dp1[N], dp2[N], same[N];
12 int s[N], top;
13 
14 int find1(int x) {
15     int l = 0, r = top, m, mk = -1;
16     while (l <= r) {
17         m = l + r >> 1;
18         if (s[m] >= x) mk = m, l = m + 1;
19         else r = m - 1;
20     }
21     return mk;
22 }
23 
24 void DP1(int n) {
25     top = -1;
26     for (int i = n - 1; i >= 0; i--) {
27         int pos = find1(rec[i]) + 1;
28         dp1[i] = pos + 1;
29         if (pos > top) s[++top] = rec[i];
30         else s[pos] = max(s[pos], rec[i]);
31     }
32 }
33 
34 void DP2(int n) {
35     top = -1;
36     for (int i = n - 1; i >= 0; i--) {
37         int pos = (int) (upper_bound(s, s + top + 1, rec[i]) - s);
38         dp2[i] = pos + 1;
39         if (pos > top) s[++top] = rec[i];
40         else s[pos] = min(s[pos], rec[i]);
41         same[i] = upper_bound(s, s + top + 1, rec[i]) - lower_bound(s, s + top + 1, rec[i]);
42     }
43 }
44 
45 int main() {
46     int n, T;
47     scanf("%d", &T);
48     while (T-- && ~scanf("%d", &n)) {
49         for (int i = 0; i < n; i++) scanf("%d", &rec[i]);
50         DP1(n);
51         DP2(n);
52         int ans = 0;
53         //for (int i = 0; i < n; i++) cout << dp1[i] << ' '; cout << endl;
54         //for (int i = 0; i < n; i++) cout << dp2[i] << ' '; cout << endl;
55         //for (int i = 0; i < n; i++) cout << same[i] << ' '; cout << endl;
56         for (int i = 0; i < n; i++) ans = max(ans, dp1[i] + dp2[i] - same[i]);
57         printf("%d
", ans);
58     }
59     return 0;
60 }
View Code

  这里的做法是计算LIS了,然后去掉重复。可是根据题意,对于下面一组数据是应该输出5的:

5

1 1 11 1 1

  不管了,先放着。

Problem - 4602

  这题是用插板法,排列组合的题。队友出的,注意的是k有可能大于n:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <map>
 6 #include <queue>
 7 #include <stack>
 8 #include <set>
 9 
10 using namespace std;
11 
12 typedef long long LL;
13 const LL MOD = 1e9 + 7;
14 
15 LL powmod(LL a, LL b) {
16     LL ret = 1;
17     while (b > 0) {
18         if (b & 1) ret *= a, ret %= MOD;
19         a *= a, a %= MOD;
20         b >>= 1;
21     }
22     return ret;
23 }
24 
25 int main() {
26     int T;
27     LL n, k;
28     cin >> T;
29     while (T-- && ~scanf("%I64d%I64d", &n, &k)) {
30         if (n == k) puts("1");
31         else if (n == k + 1) puts("2");
32         else if (k < n){
33             printf("%I64d
", (powmod(2, n - k) + (n - k - 1) * powmod(2, n - k - 2)) % MOD);
34         } else puts("0");
35     }
36     return 0;
37 }
View Code

Problem - 4608

  这题是最水的了,不过真的很没状态啊,居然搞很久才过,幸亏1y了。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <map>
 6 #include <queue>
 7 #include <stack>
 8 #include <set>
 9 
10 using namespace std;
11 
12 const int N = 111111;
13 
14 char str[N];
15 int main() {
16     int T;
17     cin >> T;
18     while (T-- && cin >> str) {
19         int len = strlen(str), pos;
20         int sum = 0;
21         for (int i = 0; i < len; i++) sum += str[i] - '0';
22         sum %= 10;
23         sum = 10 - sum;
24         if (str[len - 1] - '0' + sum < 10) {
25             str[len - 1] += sum;
26             puts(str);
27         } else {
28             str[len - 1] = '0';
29             pos = len - 2;
30             while (pos >= 0 && str[pos] == '9') str[pos--] = '0';
31             if (pos < 0) {
32                 putchar('1');
33                 str[len - 1] = 0;
34                 printf("%s", str);
35                 puts("9");
36             } else {
37                 sum = 0;
38                 str[pos]++;
39                 for (int i = 0; i < len; i++) sum += str[i] - '0';
40                 sum %= 10;
41                 str[len - 1] += (10 - sum) % 10;
42                 puts(str);
43             }
44         }
45     }
46     return 0;
47 }
View Code

  之后会陆续补充题解!

  这次真的很没状态,代码各种没平时的飘逸。。需要调整一下!

UPD:

 Problem - 4609

  FFT,比赛的时候想到了比较接近的模型,可惜没有继续想下去。这里我们可以通过FFT达到快速完成多项式乘法的效果。最后debug了好久,多次发现因为有些变量没有用long long,wa了几次。

  题意十分简单,就是给出若干边,问可以构成三角形的概率是多少。这里可以先求出反面例子,也就是两条边a+b<=c的情况,就是这里用了FFT,然后就是用全部情况减去枚举的每一个结果就行了。

带debug的代码如下:

  1 #define code 1
  2 
  3 #if (code == 1)
  4 
  5 #include <cstdio>
  6 #include <cstring>
  7 #include <iostream>
  8 #include <algorithm>
  9 #include <cmath>
 10 
 11 using namespace std;
 12 
 13 const int N = 1 << 17;
 14 const double PI = acos(-1.0);
 15 
 16 struct Vir {
 17     double r, i;
 18     Vir() {}
 19     Vir(double r, double i) : r(r), i(i) {}
 20     Vir operator + (Vir &x) { return Vir(r + x.r, i + x.i);}
 21     Vir operator - (Vir &x) { return Vir(r - x.r, i - x.i);}
 22     Vir operator * (Vir &x) { return Vir(r * x.r - i * x.i, r * x.i + i * x.r);}
 23 } rev[N << 1], v1[N << 1], v2[N << 1];
 24 
 25 const int M = 22;
 26 int ep[M];
 27 double base[M], cosb[M], sinb[M];
 28 
 29 void PRE() {
 30     ep[0] = 1;
 31     for (int i = 1; i < M; i++) ep[i] = ep[i - 1] << 1;
 32     for (int i = 0; i < M - 1; i++) base[i] = 2 * PI / ep[i + 1];
 33     for (int i = 0; i < M - 1; i++) sinb[i] = sin(base[i]), cosb[i] = cos(base[i]);
 34 }
 35 
 36 inline int revbit(int x, int l) {
 37     int ret = 0;
 38     while (l--) ret <<= 1, ret |= x & 1, x >>= 1;
 39     return ret;
 40 }
 41 
 42 inline void reverse(Vir *a, int len) {
 43     int bits = (int) ceil(log((double) len) / log(2.0));
 44     for (int i = 0; i < len; i++) rev[revbit(i, bits)] = a[i];
 45     for (int i = 0; i < len; i++) a[i] = rev[i];
 46 }
 47 
 48 const Vir unit = Vir(1.0, 0.0);
 49 
 50 void fft(Vir *a, int len, bool idft) {
 51     Vir u, t;
 52     int bits = (int) ceil(log((double) len) / log(2.0));
 53     reverse(a, len);
 54     for (int i = 0; i < bits; i++) {
 55         Vir wi, w;
 56         wi.r = cosb[i];
 57         wi.i = idft ? -sinb[i] : sinb[i];
 58         for (int k = 0; k < len; k+= ep[i + 1]) {
 59             w = unit;
 60             for (int j = 0; j < ep[i]; j++) {
 61                 t = w * a[k + j + ep[i]];
 62                 u = a[k + j];
 63                 a[k + j] = u + t;
 64                 a[k + j + ep[i]] = u - t;
 65                 w = w * wi;
 66             }
 67         }
 68     }
 69     if (idft) for (int i = 0; i < len; i++) a[i].r /= len;
 70 }
 71 
 72 void cal(Vir *a, Vir *b, int len) {
 73     fft(a, len, 0);
 74     fft(b, len, 0);
 75     for (int i = 0; i < len; i++) a[i] = a[i] * b[i];
 76     fft(a, len, 1);
 77 }
 78 
 79 int rec[N];
 80 typedef long long LL;
 81 LL cnt[N << 1];
 82 
 83 bool test(int a, int b, int c) {
 84     if (a + b <= c) return false;
 85     if (a + c <= b) return false;
 86     if (b + c <= a) return false;
 87     return true;
 88 }
 89 
 90 double BF(int n) {
 91     int cnt = 0;
 92     for (int i = 0; i < n; i++) {
 93         for (int j = i + 1; j < n; j++) {
 94             for (int k = j + 1; k < n; k++) {
 95                 cnt += test(rec[i], rec[j], rec[k]);
 96             }
 97         }
 98     }
 99     return 6.0 * cnt / (n * (n - 1) * (n - 2));
100 }
101 
102 int main() {
103 //    freopen("in", "r", stdin);
104     int n, x, T;
105     PRE();
106     cin >> T;
107     while (T-- && cin >> n) {
108         memset(v1, 0, sizeof(v1));
109         memset(v2, 0, sizeof(v2));
110         int mx = 0;
111         for (int i = 0; i < n; i++) {
112             scanf("%d", &x);
113             rec[i] = x;
114             v1[x].r += 1.0;
115             v2[x].r += 1.0;
116             mx = max(x, mx);
117         }
118         mx++;
119         int len = 0;
120         while (ep[len] < mx) len++;
121         len = ep[len + 1];
122         cal(v1, v2, len);
123 //        cout << len << endl;
124         LL tt = (LL) n * (n - 1) * (n - 2) / 6, ans = tt;
125 //        cout << tt << endl;
126         for (int i = 0; i < len; i++) cnt[i] = (LL) floor(v1[i].r + 0.5);
127 //        for (int i = 0; i < 16; i++) cout << i << ' ' << v1[i].r << endl;
128         for (int i = 0; i < n; i++) cnt[rec[i] << 1]--;
129 //        for (int i = 0; i < 16; i++) cout << i << ' ' << cnt[i] << endl;
130         for (int i = 0; i < len; i++) {
131             cnt[i] >>= 1;
132             cnt[i] += cnt[i - 1];
133         }
134         for (int i = 0; i < n; i++) ans -= cnt[rec[i]];
135 //        cout << ans << endl;
136         printf("%.7f
", ans * 1.0 / tt);
137 //        double ansbf;
138 //        printf("%.7f BruceForce~~~
", ansbf = BF(n));
139 //        if (fabs(ans * 1.0 / tt - ansbf) > 1e-7) {
140 //            freopen("out", "w", stdout);
141 //            puts("1");
142 //            cout << n << endl;
143 //            for (int i = 0; i < n; i++) cout << rec[i] << ' '; cout << endl;
144 //            puts("WTF?!?!?!?!?!");
145 //            break;
146 //        }
147     }
148     return 0;
149 }
150 
151 #else
152 
153 #include <cstdio>
154 #include <cstring>
155 #include <iostream>
156 #include <algorithm>
157 #include <ctime>
158 #include <cmath>
159 
160 using namespace std;
161 
162 const int T = 1000;
163 const int MAXN = 1000;
164 const int DIF = 10;
165 const int MAXNUM = 100000;
166 
167 int main() {
168     freopen("in", "w", stdout);
169     cout << 1 << endl << 100000 << endl;
170     for (int i = 0; i < 100000; i++) cout << rand() % 2 + 1 << ' '; cout << endl;
171 //    int t = T >> 2;
172 //    srand(time(0));
173 //    cout << T << endl;
174 //    while (t--) {
175 //        int n = MAXN - DIF + 1 + rand() % DIF;
176 //        cout << n << endl;
177 //        while (n--) cout << rand() % 10 + 1 << ' ';
178 //        cout << endl;
179 //    }
180 //    t = T >> 2;
181 //    while (t--) {
182 //        int n = MAXN - DIF + 1 + rand() % DIF;
183 //        cout << n << endl;
184 //        while (n--) cout << rand() % 100 + 1 << ' ';
185 //        cout << endl;
186 //    }
187 //    t = T >> 2;
188 //    while (t--) {
189 //        int n = MAXN - DIF + 1 + rand() % DIF;
190 //        cout << n << endl;
191 //        while (n--) cout << rand() % 1000 + 1 << ' ';
192 //        cout << endl;
193 //    }
194 //    t = T >> 2;
195 //    while (t--) {
196 //        int n = MAXN - DIF + 1 + rand() % DIF;
197 //        cout << n << endl;
198 //        while (n--) cout << rand() % MAXNUM + 1 << ' ';
199 //        cout << endl;
200 //    }
201     return 0;
202 }
203 
204 #endif
View Code

  上面的代码写了个暴力对拍,可惜最后还是想到数据,然后找到错误的数据,最后修改过来通过的。

代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 
  7 using namespace std;
  8 
  9 const int N = 1 << 17;
 10 const double PI = acos(-1.0);
 11 
 12 struct Vir {
 13     double r, i;
 14     Vir() {}
 15     Vir(double r, double i) : r(r), i(i) {}
 16     Vir operator + (Vir &x) { return Vir(r + x.r, i + x.i);}
 17     Vir operator - (Vir &x) { return Vir(r - x.r, i - x.i);}
 18     Vir operator * (Vir &x) { return Vir(r * x.r - i * x.i, r * x.i + i * x.r);}
 19 } rev[N << 1], v1[N << 1], v2[N << 1];
 20 
 21 const int M = 22;
 22 int ep[M];
 23 double base[M], cosb[M], sinb[M];
 24 
 25 void PRE() {
 26     ep[0] = 1;
 27     for (int i = 1; i < M; i++) ep[i] = ep[i - 1] << 1;
 28     for (int i = 0; i < M - 1; i++) base[i] = 2 * PI / ep[i + 1];
 29     for (int i = 0; i < M - 1; i++) sinb[i] = sin(base[i]), cosb[i] = cos(base[i]);
 30 }
 31 
 32 inline int revbit(int x, int l) {
 33     int ret = 0;
 34     while (l--) ret <<= 1, ret |= x & 1, x >>= 1;
 35     return ret;
 36 }
 37 
 38 inline void reverse(Vir *a, int len) {
 39     int bits = (int) ceil(log((double) len) / log(2.0));
 40     for (int i = 0; i < len; i++) rev[revbit(i, bits)] = a[i];
 41     for (int i = 0; i < len; i++) a[i] = rev[i];
 42 }
 43 
 44 const Vir unit = Vir(1.0, 0.0);
 45 
 46 void fft(Vir *a, int len, bool idft) {
 47     Vir u, t;
 48     int bits = (int) ceil(log((double) len) / log(2.0));
 49     reverse(a, len);
 50     for (int i = 0; i < bits; i++) {
 51         Vir wi, w;
 52         wi.r = cosb[i];
 53         wi.i = idft ? -sinb[i] : sinb[i];
 54         for (int k = 0; k < len; k+= ep[i + 1]) {
 55             w = unit;
 56             for (int j = 0; j < ep[i]; j++) {
 57                 t = w * a[k + j + ep[i]];
 58                 u = a[k + j];
 59                 a[k + j] = u + t;
 60                 a[k + j + ep[i]] = u - t;
 61                 w = w * wi;
 62             }
 63         }
 64     }
 65     if (idft) for (int i = 0; i < len; i++) a[i].r /= len;
 66 }
 67 
 68 void cal(Vir *a, Vir *b, int len) {
 69     fft(a, len, 0);
 70     fft(b, len, 0);
 71     for (int i = 0; i < len; i++) a[i] = a[i] * b[i];
 72     fft(a, len, 1);
 73 }
 74 
 75 int rec[N];
 76 typedef long long LL;
 77 LL cnt[N << 1];
 78 
 79 bool test(int a, int b, int c) {
 80     if (a + b <= c) return false;
 81     if (a + c <= b) return false;
 82     if (b + c <= a) return false;
 83     return true;
 84 }
 85 
 86 double BF(int n) {
 87     int cnt = 0;
 88     for (int i = 0; i < n; i++) {
 89         for (int j = i + 1; j < n; j++) {
 90             for (int k = j + 1; k < n; k++) {
 91                 cnt += test(rec[i], rec[j], rec[k]);
 92             }
 93         }
 94     }
 95     return 6.0 * cnt / (n * (n - 1) * (n - 2));
 96 }
 97 
 98 int main() {
 99     int n, x, T;
100     PRE();
101     cin >> T;
102     while (T-- && cin >> n) {
103         memset(v1, 0, sizeof(v1));
104         memset(v2, 0, sizeof(v2));
105         int mx = 0;
106         for (int i = 0; i < n; i++) {
107             scanf("%d", &x);
108             rec[i] = x;
109             v1[x].r += 1.0;
110             v2[x].r += 1.0;
111             mx = max(x, mx);
112         }
113         mx++;
114         int len = 0;
115         while (ep[len] < mx) len++;
116         len = ep[len + 1];
117         cal(v1, v2, len);
118         LL tt = (LL) n * (n - 1) * (n - 2) / 6, ans = tt;
119         for (int i = 0; i < len; i++) cnt[i] = (LL) floor(v1[i].r + 0.5);
120         for (int i = 0; i < n; i++) cnt[rec[i] << 1]--;
121         for (int i = 0; i < len; i++) {
122             cnt[i] >>= 1;
123             cnt[i] += cnt[i - 1];
124         }
125         for (int i = 0; i < n; i++) ans -= cnt[rec[i]];
126         printf("%.7f
", ans * 1.0 / tt);
127     }
128     return 0;
129 }
View Code

 UPD:

 Problem - 4605

  题意是,给定一棵点上带权的树,要求求出从根出发到达给定结点按照要求求出的概率值。

  这题可以有很多做法,比较容易想到的可能是树链剖分,不过这题用树链剖分的话估计vector之类的stl会导致超时。这题有一个简单的方法,就是在遍历树的时候同时处理query,也就是离线处理。遍历的过程中,记录两样东西,一个是从根结点到当前结点有哪些权值,另一个是从根结点到当前结点需要向右走的结点有哪些权值。

  遍历到当前结点的时候,求出有多少个已存的权值比当前权值小和大,还有多少个已存的向右走的结点的权值比当前权值小。

  加了个栈挂,1y~

代码如下:

  1 #pragma comment(linker, "/STACK:102400000,102400000")
  2 
  3 #include <cstdio>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <cstring>
  7 #include <map>
  8 
  9 using namespace std;
 10 
 11 const int N = 111111;
 12 struct Node {
 13     int w, c[2];
 14 } node[N];
 15 map<int, int> id;
 16 int rx[N];
 17 
 18 inline int lowbit(int x) { return x & (-x);}
 19 struct BIT {
 20     int s[N << 1], sz, tt;
 21     void init(int size) { memset(s, 0, sizeof(s)); sz = size + 10, tt = 0;}
 22     void inc(int x) { tt++, x += 10; for ( ; x < N; x += lowbit(x)) s[x]++;}
 23     void dec(int x) { tt--, x += 10; for ( ; x < N; x += lowbit(x)) s[x]--;}
 24     int sum(int x) {
 25         int ret = 0;
 26         for (x += 10; x > 0; x -= lowbit(x)) ret += s[x];
 27         return ret;
 28     }
 29     int sum(int l, int r) { return sum(r) - sum(l - 1);}
 30 } all, rt;
 31 
 32 struct Query {
 33     int x, nx, id;
 34     Query() {}
 35     Query(int x, int nx, int id) : x(x), nx(nx), id(id) {}
 36 } qry[N];
 37 int qs[N], qc;
 38 int q1[N], q2[N], cnt[N];
 39 
 40 void init() {
 41     memset(qs, -1, sizeof(qs));
 42     qc = 0;
 43 }
 44 
 45 void addqry(int v, int x, int id) {
 46     qry[qc] = Query(x, qs[v], id);
 47     qs[v] = qc++;
 48 }
 49 
 50 void dfs(int x) {
 51     int wt = id[node[x].w], t;
 52     for (t = qs[x]; ~t; t = qry[t].nx) {
 53         Query &q = qry[t];
 54         if (cnt[id[q.x]]) {
 55             q1[q.id] = -1;
 56             continue;
 57         }
 58         int w = id[q.x];
 59         int lwr = all.sum(w - 1), upr = all.tt - lwr - cnt[w];
 60         int lw = rt.sum(w - 1);
 61         q1[q.id] = lw;
 62         q2[q.id] = upr + lwr * 3;
 63     }
 64     all.inc(wt);
 65     cnt[wt]++;
 66     if (~node[x].c[0]) dfs(node[x].c[0]);
 67     rt.inc(wt);
 68     if (~node[x].c[1]) dfs(node[x].c[1]);
 69     rt.dec(wt);
 70     all.dec(wt);
 71     cnt[wt]--;
 72 }
 73 
 74 bool nrt[N];
 75 
 76 int main() {
 77 //    freopen("in", "r", stdin);
 78     int T, n, m, q;
 79     int x, y, f;
 80     scanf("%d", &T);
 81     while (T-- && ~scanf("%d", &n)) {
 82         id.clear();
 83         for (int i = 1; i <= n; i++) {
 84             scanf("%d", &node[i].w);
 85             rx[i - 1] = node[i].w;
 86             node[i].c[0] = node[i].c[1] = -1;
 87         }
 88         memset(nrt, 0, sizeof(nrt));
 89         scanf("%d", &m);
 90         while (m--) {
 91             scanf("%d%d%d", &f, &x, &y);
 92             node[f].c[0] = x, node[f].c[1] = y;
 93             nrt[x] = nrt[y] = true;
 94         }
 95         init();
 96         scanf("%d", &q);
 97         for (int i = 0; i < q; i++) {
 98             scanf("%d%d", &x, &y);
 99             rx[i + n] = y;
100             addqry(x, y, i);
101         }
102         sort(rx, rx + n + q);
103         m = (int) (unique(rx, rx + n + q) - rx);
104         all.init(m);
105         rt.init(m);
106         for (int i = 0; i < m; i++) id[rx[i]] = i;
107         int rt = -1;
108         for (int i = 1; i <= n; i++) if (!nrt[i]) rt = i;
109         if (rt == -1) {
110             puts("WTF?!");
111             while (1) ;
112         }
113         dfs(1);
114         for (int i = 0; i < q; i++) {
115             if (q1[i] == -1) puts("0");
116             else printf("%d %d
", q1[i], q2[i]);
117         }
118     }
119     return 0;
120 }
View Code

 UPD:

  改成非递归的:

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <map>
  6 
  7 using namespace std;
  8 
  9 const int N = 111111;
 10 struct Node {
 11     int w, c[2];
 12 } node[N];
 13 map<int, int> id;
 14 int rx[N];
 15 
 16 inline int lowbit(int x) { return x & (-x);}
 17 struct BIT {
 18     int s[N << 1], sz, tt;
 19     void init(int size) { memset(s, 0, sizeof(s)); sz = size + 10, tt = 0;}
 20     void inc(int x) { tt++, x += 10; for ( ; x < N; x += lowbit(x)) s[x]++;}
 21     void dec(int x) { tt--, x += 10; for ( ; x < N; x += lowbit(x)) s[x]--;}
 22     int sum(int x) {
 23         int ret = 0;
 24         for (x += 10; x > 0; x -= lowbit(x)) ret += s[x];
 25         return ret;
 26     }
 27     int sum(int l, int r) { return sum(r) - sum(l - 1);}
 28 } all, rt;
 29 
 30 struct Query {
 31     int x, nx, id;
 32     Query() {}
 33     Query(int x, int nx, int id) : x(x), nx(nx), id(id) {}
 34 } qry[N];
 35 int qs[N], qc;
 36 int q1[N], q2[N], cnt[N];
 37 
 38 void init() {
 39     memset(qs, -1, sizeof(qs));
 40     qc = 0;
 41 }
 42 
 43 void addqry(int v, int x, int id) {
 44     qry[qc] = Query(x, qs[v], id);
 45     qs[v] = qc++;
 46 }
 47 
 48 int sv[N], top;
 49 int vis[N];
 50 void dfs(int x) {
 51     top = -1;
 52     sv[++top] = x;
 53     vis[top] = 0;
 54     while (top >= 0) {
 55         x = sv[top];
 56         int st = vis[top--], wt = id[node[x].w], t;
 57         if (st == 0) {
 58             for (t = qs[x]; ~t; t = qry[t].nx) {
 59                 Query &q = qry[t];
 60                 if (cnt[id[q.x]]) {
 61                     q1[q.id] = -1;
 62                     continue;
 63                 }
 64                 int w = id[q.x];
 65                 int lwr = all.sum(w - 1), upr = all.tt - lwr - cnt[w];
 66                 int lw = rt.sum(w - 1);
 67                 q1[q.id] = lw;
 68                 q2[q.id] = upr + lwr * 3;
 69             }
 70             all.inc(wt);
 71             cnt[wt]++;
 72             sv[++top] = x;
 73             vis[top] = 1;
 74             if (~node[x].c[0]) sv[++top] = node[x].c[0], vis[top] = 0;
 75         } else if (st == 1) {
 76             rt.inc(wt);
 77             sv[++top] = x;
 78             vis[top] = 2;
 79             if (~node[x].c[1]) sv[++top] = node[x].c[1], vis[top] = 0;
 80         } else {
 81             rt.dec(wt);
 82             all.dec(wt);
 83             cnt[wt]--;
 84         }
 85     }
 86 }
 87 
 88 bool nrt[N];
 89 
 90 int main() {
 91 //    freopen("in", "r", stdin);
 92     int T, n, m, q;
 93     int x, y, f;
 94     scanf("%d", &T);
 95     while (T-- && ~scanf("%d", &n)) {
 96         id.clear();
 97         for (int i = 1; i <= n; i++) {
 98             scanf("%d", &node[i].w);
 99             rx[i - 1] = node[i].w;
100             node[i].c[0] = node[i].c[1] = -1;
101         }
102         memset(nrt, 0, sizeof(nrt));
103         scanf("%d", &m);
104         while (m--) {
105             scanf("%d%d%d", &f, &x, &y);
106             node[f].c[0] = x, node[f].c[1] = y;
107             nrt[x] = nrt[y] = true;
108         }
109         init();
110         scanf("%d", &q);
111         for (int i = 0; i < q; i++) {
112             scanf("%d%d", &x, &y);
113             rx[i + n] = y;
114             addqry(x, y, i);
115         }
116         sort(rx, rx + n + q);
117         m = (int) (unique(rx, rx + n + q) - rx);
118         all.init(m);
119         rt.init(m);
120         for (int i = 0; i < m; i++) id[rx[i]] = i;
121         int rt = -1;
122         for (int i = 1; i <= n; i++) if (!nrt[i]) rt = i;
123         if (rt == -1) {
124             puts("WTF?!");
125             while (1) ;
126         }
127         dfs(1);
128         for (int i = 0; i < q; i++) {
129             if (q1[i] == -1) puts("0");
130             else printf("%d %d
", q1[i], q2[i]);
131         }
132     }
133     return 0;
134 }
View Code

 UPD:

  贴一下队友ly的1008(hdu 4607)的代码:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <map>
 6 #include <queue>
 7 #include <stack>
 8 #include <set>
 9 
10 const int N = 1e5+5;
11 const int inf = 1<<28;
12 using namespace std;
13 int n,m;
14 int tot,pre[N];
15 struct edge{
16     int v,next;
17 }e[N<<1];
18 
19 void init(){
20     tot=0;
21     memset(pre,-1,sizeof(pre));
22 }
23 
24 void add(int u,int v){
25     edge E={v,pre[u]};
26     e[tot]=E,pre[u]=tot++;
27 }
28 
29 void input(){
30     int u,v;
31     scanf("%d%d",&n,&m);
32     for(int i=1;i<n;i++){
33         scanf("%d%d",&u,&v);
34         add(u,v),add(v,u);
35     }
36 }
37 
38 int dis[N],vis[N];
39 int bfs(int s,int &t){
40     queue<int> q;
41     memset(vis,0,sizeof(vis));
42     dis[s]=0,vis[s]=1,t=s;
43     q.push(s);
44     int res=0;
45     while(!q.empty()){
46         int u=q.front();
47         q.pop();
48         if(res<dis[u]){
49             res=dis[u];
50             t=u;
51         }
52         for(int i=pre[u];i!=-1;i=e[i].next){
53             int v=e[i].v;
54             if(!vis[v]){
55                 dis[v]=dis[u]+1;
56                 vis[v]=1;
57                 q.push(v);
58             }
59         }
60     }
61     return res+1;
62 }
63 
64 void query(){
65     int k,u,v;
66     int tmp=bfs(1,v);
67     tmp=bfs(v,u);
68     while(m--){
69         scanf("%d",&k);
70         if(k<=tmp) printf("%d
",k-1);
71         else printf("%d
",tmp-1+(k-tmp)*2);
72     }
73 }
74 
75 int main(){
76     int t;
77     scanf("%d",&t);
78     while(t--){
79         init();
80         input();
81         query();
82     }
83     return 0;
84 }
View Code

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/2013_07_23_Lyon.html