码迷,mamicode.com
首页 > 其他好文 > 详细

3641-货车运输-函数式线段树-分类讨论-环套树

时间:2015-04-03 00:06:51      阅读:338      评论:0      收藏:0      [点我收藏+]

标签:

3641: 货车运输

Time Limit: 20 Sec  Memory Limit: 256 MBSec  Special Judge
Submit: 64  Solved: 27
[Submit][Status][Discuss]

Description

saffah所在的国家一共有N个城市,通过N条双向道路连接,使得城市之间两两可以到达。第i条道路连接了A[i]与B[i],其长度为L[i] km。
这些道路分为M个等级。第i条道路的等级为X[i]。在第j级道路上行驶,你的限速是V[j] km/h,并且每行驶1小时会收取W[j]元的费用。根据道路分级的意义,V[j]与W[j]都随着j单调变化,即对于1 ≤ j < M,满足V[j] > V[j+1], W[j] > W[j+1]。
现在有Q辆货车需要运送货物。第k辆货车要从S[k]前往T[k],并且其最大速度为U[k] km/h。你需要对每辆货车求出其最小运送花费。

 

Input

第一行三个整数N, M, Q。
接下来N行,每行四个整数A[i], B[i], L[i], X[i],描述了一条道路。
接下来M行,每行两个整数V[j], W[j],描述了一个道路等级的限速和费用。
接下来Q行,每行三个整数S[k], T[k], U[k],描述了一辆货车。

 

Output

输出Q行,即每辆货车的最小运送花费。
你可以输出任意多位的实数,只要与标准答案的相对或绝对误差不超过0.0001就算正确。

 

Sample Input

4 2 2
1 2 50 1
2 3 50 1
1 3 50 2
3 4 50 1
100 20
10 10
1 4 100
1 4 10

Sample Output

30
150

HINT

 

对于所有的数据,1 ≤ N,M,Q ≤ 100,000, 1 ≤ A[i],B[i],S[k],T[k] ≤ N, 1 ≤ X[i] ≤ M, 1 ≤ L[i],V[j],W[j],U[k] ≤ 500,000。

样例解释:

第一辆货车应该沿1→2→3→4行驶,共在1级道路上行驶1.5小时,收费30元。

第二辆货车应该沿1→3→4行驶,在2级道路上行驶5小时,在1级道路上行驶5小时,收费150元。

 

出题人真是调皮,上来就给8个数组。。

傻逼代码题。。调了蛮久(主要是数据。。找了半天。。CH各种坑啊。。)。。最后发现

技术分享
    rep(i, 1, cCnt) {
        dep[cir[i]] = 1;
    }
View Code

写成:

    rep(i, 1, cCnt) {
        dep[i] = 1;
    }

23333

rk3的代码。。

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <cmath>
  6 #include <string>
  7 #include <vector>
  8 #include <map>
  9 #include <set>
 10 #include <queue>
 11 #include <climits>
 12 #include <cstdlib>
 13 #include <ctime>
 14 using namespace std;
 15 namespace my_useful_tools {
 16 #define rep(_i, _k, _j) for(int _i = _k; _i <= _j; ++_i)
 17 #define reu(_i, _k, _j) for(int _i = _k; _i <  _j; ++_i)
 18 #define red(_i, _k, _j) for(int _i = _k; _j <= _i; --_i)
 19 #define foreach(_i, _s) for(typeof(_s.begin()) _i = _s.begin(); _i != _s.end(); ++_i)
 20 #define pb push_back
 21 #define mp make_pair
 22 #define ipir pair<int, int>
 23 #define ivec vector<int>
 24 #define clr(t) memset(t, 0, sizeof t)
 25 #define pse(t, v) memset(t, v, sizeof t)
 26 #define brl puts("")
 27 #define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
 28 #define file_hza freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
 29 #define file_gen(x) freopen(#x".in", "w", stdout);
 30     const int INF = 0x3f3f3f3f;
 31     typedef long long LL;
 32     typedef long double DB;
 33     inline void pc(char c) { putchar(c); }
 34     template<class T> inline T gcd(T a, T b) { return b == 0 ? a : gcd(b, a % b); }
 35     inline char gchar() { char ret = getchar(); for(; ret == \n || ret == \r || ret ==  ; ret = getchar()); return ret; }
 36     template<class T> inline void fr(T&ret) { char c =  ; int flag = 1; for(c = getchar(); c != - && !(0 <= c && c <= 9); c = getchar()); 
 37         if(c == -) flag = -1, ret = 0; else ret = c - 0; for(c = getchar(); 0 <= c && c <= 9; c = getchar()) ret = ret * 10 + c - 0;
 38         ret = ret * flag;
 39     }
 40     inline int fr() { int x; fr(x); return x; }
 41     template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); }
 42     template<class T> inline T fast_pow(T base, T index, T mod = 2147483647, T ret = 1) {
 43         for(; index; index >>= 1, base = base * base % mod) if(index & 1) ret = ret * base % mod;
 44         return ret;
 45     }
 46 };
 47 using namespace my_useful_tools;
 48 
 49 const int maxn = 1e5 + 100;
 50 
 51 
 52 int e, h[maxn], to[maxn*2], nxt[maxn*2], dis[maxn*2], rnk[maxn*2];
 53 void addEdge(int u, int v, int c, int d) {
 54     nxt[e] = h[u], to[e] = v, rnk[e] = c, dis[e] = d, h[u] = e++;
 55     nxt[e] = h[v], to[e] = u, rnk[e] = c, dis[e] = d, h[v] = e++;
 56 }
 57 
 58 int V[maxn], W[maxn];
 59 int n, m, q;
 60 
 61 int fa[maxn], pa[maxn][21], cir[maxn], cCnt, onCir[maxn], dep[maxn], owner[maxn], lnk[maxn];
 62 
 63 void get_cir(int u) {
 64     //printf("%d\n", u);
 65     for (int i=h[u]; i !=-1; i=nxt[i]) {
 66         if (i != fa[u]) {
 67             if (dep[to[i]] > 0) {
 68                 cir[++cCnt] = u;
 69                 lnk[cCnt] = fa[u];
 70                 while (u != to[i]) {
 71                     u = to[fa[u]];
 72                     cir[++cCnt] = u;
 73                     lnk[cCnt] = fa[u];
 74                 }
 75                 lnk[cCnt] = i;
 76                 break;
 77             }
 78             fa[to[i]] = i^1;
 79             dep[to[i]] = dep[u]+1;
 80             get_cir(to[i]);
 81             if (cCnt != 0) break;
 82         }
 83     }
 84 }
 85 
 86 const int maxNode = ((maxn<<2)+maxn*30)*2;
 87 #define cn cmt_node
 88 #define lc ch[0]
 89 #define rc ch[1]
 90 struct cmt_node {
 91     cn*ch[2];
 92     long double a, b;
 93     cn() {
 94         ch[0] = ch[1] = NULL;
 95         a = b = 0.0;
 96     }
 97 } pool[maxNode], *loc=pool, *root, *trt[maxn], *crt[maxn];
 98 
 99 void build(int l, int r, cn*&rt) {
100     if (rt == NULL)
101         rt = loc++;
102     if (l == r) return ;
103     int mid=(l+r)>>1;
104     build(l, mid, rt->lc);
105     build(mid+1, r, rt->rc);
106 }
107 
108 int rk;
109 long double aa, ab;
110 void insert(int l, int r, cn*&rt, cn*pre) {
111     rt = loc++;
112     rt->a = pre->a+aa, rt->b = pre->b+ab;
113     if (l == r) return ;
114     int mid = (l+r)>>1;
115     if (rk <= mid) rt->rc=pre->rc, insert(l, mid, rt->lc, pre->lc);
116     else rt->lc=pre->lc, insert(mid+1, r, rt->rc, pre->rc);
117 }
118 long double queryA(int ql, int qr, int l, int r, cn*ra, cn*rb, cn*f) {
119     if (ql <= l && r <= qr) {
120         return ra->a + rb->a - 2.0*f->a;
121     }
122     int mid = (l+r)>>1;
123     long double ret = 0.0;
124     if (ql <= mid) ret += queryA(ql, qr, l, mid, ra->lc, rb->lc, f->lc);
125     if (mid < qr) ret += queryA(ql, qr, mid+1, r, ra->rc, rb->rc, f->rc);
126     return ret;
127 }
128 long double queryB(int ql, int qr, int l, int r, cn*ra, cn*rb, cn*f) {
129     if (ql <= l && r <= qr) {
130         return ra->b + rb->b - 2.0*f->b;
131     }
132     int mid = (l+r)>>1;
133     long double ret = 0.0;
134     if (ql <= mid) ret += queryB(ql, qr, l, mid, ra->lc, rb->lc, f->lc);
135     if (mid < qr) ret += queryB(ql, qr, mid+1, r, ra->rc, rb->rc, f->rc);
136     return ret;
137 }
138 long double queryA(int ql, int qr, int l, int r, cn*ra, cn*rb) {
139     if (ql <= l && r <= qr) {
140         return rb->a - ra->a;
141     }
142     int mid = (l+r)>>1;
143     long double ret = 0.0;
144     if (ql <= mid) ret += queryA(ql, qr, l, mid, ra->lc, rb->lc);
145     if (mid < qr) ret += queryA(ql, qr, mid+1, r, ra->rc, rb->rc);
146     return ret;
147 }
148 long double queryB(int ql, int qr, int l, int r, cn*ra, cn*rb) {
149     if (ql <= l && r <= qr) {
150         return rb->b - ra->b;
151     }
152     int mid = (l+r)>>1;
153     long double ret = 0.0;
154     if (ql <= mid) ret += queryB(ql, qr, l, mid, ra->lc, rb->lc);
155     if (mid < qr) ret += queryB(ql, qr, mid+1, r, ra->rc, rb->rc);
156     return ret;
157 }
158 
159 void dfs(int u, int f, int top) {
160     /*
161     if (u == 93078) {
162         printf("93078 %d\n", top);
163     }
164     if (u == 14257) {
165         printf("14257 %d\n", top);
166     }
167     */
168     owner[u] = top;
169     //pa[u][0] = f;
170     for (int i=h[u]; i!=-1; i=nxt[i])
171         if (to[i] != f && !onCir[to[i]]) {
172             pa[to[i]][0] = u;
173             dep[to[i]] = dep[u]+1;
174             rk = rnk[i];
175             aa = (DB)dis[i]*W[rk];
176             ab = (DB)dis[i]/V[rk]*W[rk];
177             insert(1, m, trt[to[i]], trt[u]);
178             dfs(to[i], u, top);
179         }
180 }
181 
182 int lca(int u, int v) {
183     if (dep[u] < dep[v]) swap(u, v);
184     red(i, 20, 0)
185         if (dep[pa[u][i]] >= dep[v])
186             u = pa[u][i];
187     if (u == v) return u;
188     red(i, 20, 0)
189         if (pa[u][i] != pa[v][i])
190             u=pa[u][i], v=pa[v][i];
191     return pa[u][0];
192 }
193 
194 vector<int> rV;
195 vector<int>::iterator it;
196 int getRank(int u) {
197     it = upper_bound(rV.begin(), rV.end(), u);
198     if (it == rV.end()) return 1;
199     int v = it-rV.begin();
200     return m-v+1;
201 }
202 long double qMinCost(int s, int t, int u, int r) {
203     if (s == t) return 0;
204     int f = lca(s, t);
205     long double ret = 0.0;
206     if (1 <= r-1) ret += queryA(1, r-1, 1, m, trt[s], trt[t], trt[f])/u;
207     if (r <= m) ret += queryB(r, m, 1, m, trt[s], trt[t], trt[f]);
208     return ret;
209 }
210 long double qMinCost2(int s, int t, int u, int r) {
211     if (t <= s) return 0;
212     long double ret = 0.0;
213     if (1 <= r-1) ret += queryA(1, r-1, 1, m, crt[s], crt[t])/(long double)u;
214     if (r <= m) ret += queryB(r, m, 1, m, crt[s], crt[t]);
215     return ret;
216 }
217 
218 int main() {
219     fr(n, m, q);
220     root = NULL;
221     build(1, m, root);
222     trt[0] = crt[0] = root;
223     rep(i, 1, n) trt[i] = NULL;
224     e = 0, pse(h, -1);
225     int a, b, c, d;
226     rep(i, 1, n) {
227         fr(a, b), fr(d, c);
228         addEdge(a, b, c, d);
229     }
230     rep(i, 1, m)
231         fr(V[i], W[i]);
232     pse(fa, -1);
233     dep[1] = 1;
234     get_cir(1);
235     rep(i, 1, cCnt)
236         onCir[cir[i]] = i;
237     dep[0] = 0;
238     crt[0] = root;
239     rep(i, 1, cCnt) {
240         dep[cir[i]] = 1;
241         trt[cir[i]] = root;
242         dfs(cir[i], 0, cir[i]);
243         crt[i] = NULL;
244         int p = (i==1?lnk[cCnt]:lnk[i-1]);
245         rk = rnk[p];
246         aa = (DB)dis[p]*W[rk];
247         ab = (DB)dis[p]*W[rk]/V[rk];
248         insert(1, m, crt[i], crt[i-1]);
249     }
250     rep(j, 1, 20)
251         rep(i, 1, n)
252         pa[i][j] = pa[pa[i][j-1]][j-1];
253 
254     rep(i, 1, m)
255         rV.pb(V[i]);
256     reverse(rV.begin(), rV.end());
257     int s, t, u, r;
258     while (q--) {
259         fr(s, t, u);
260         long double ans = 0.0;
261         r = getRank(u);
262         if (owner[s] == owner[t]) {
263             ans = qMinCost(s, t, u, r);
264         } else {
265             if (onCir[owner[t]] < onCir[owner[s]])
266                 swap(s, t);
267             ans += qMinCost(s, owner[s], u, r);
268             ans += qMinCost(t, owner[t], u, r);
269             long double x = qMinCost2(onCir[owner[s]], onCir[owner[t]], u, r);
270             long double y = qMinCost2(1, onCir[owner[s]], u, r);
271             long double z = qMinCost2(onCir[owner[t]], cCnt, u, r);
272             long double w = qMinCost2(0, 1, u, r);
273             ans += min(x, y+z+w);
274         }
275         printf("%lf\n", (double)ans);
276     }
277 
278     return 0;
279 }
View Code

 

3641-货车运输-函数式线段树-分类讨论-环套树

标签:

原文地址:http://www.cnblogs.com/hzf-sbit/p/4388800.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!