您的位置:首页 > 其它

【HDOJ】4729 An Easy Problem for Elfness

2016-02-15 15:04 295 查看
其实是求树上的路径间的数据第K大的题目。
果断主席树 + LCA。
初始流量是这条路径上的最小值。
若a<=b,显然直接为s->t建立pipe可以使流量最优;
否则,对【0, 10**4】二分得到boundry,使得boundry * n_edge - sum_edge <= k/b, 或者建立s->t,然后不断extend s->t。

/* 4729 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000")

#define sti                set<int>
#define stpii            set<pair<int, int> >
#define mpii            map<int,int>
#define vi                vector<int>
#define pii                pair<int,int>
#define vpii            vector<pair<int,int> >
#define rep(i, a, n)     for (int i=a;i<n;++i)
#define per(i, a, n)     for (int i=n-1;i>=a;--i)
#define clr                clear
#define pb                 push_back
#define mp                 make_pair
#define fir                first
#define sec                second
#define all(x)             (x).begin(),(x).end()
#define SZ(x)             ((int)(x).size())
// #define lson            l, mid, rt<<1
// #define rson            mid+1, r, rt<<1|1

typedef struct {
int v, c, nxt;
} edge_t;

const int maxn = 1e5+5;
const int m = 10005;
const int maxm = maxn * 20;
int T[maxn];
int lson[maxm], rson[maxm], c[maxm], sum[maxm];
int head[maxn], l;
edge_t E[maxn<<1];
int tot, n, q;
int beg[maxn];
int V[maxn<<1], D[maxn<<1], top;
int dp[18][maxn<<1];

void init() {
memset(head, -1, sizeof(head));
l = top = 0;
tot = 1;
}

int Build(int l, int r) {
int rt = tot++;

c[rt] = sum[rt] = 0;
if (l == r)
return rt;

int mid = (l + r) >> 1;

lson[rt] = Build(l, mid);
rson[rt] = Build(mid+1, r);

return rt;
}

int Insert(int rt, int x, int val) {
int nrt = tot++, ret = nrt;
int l = 0, r = m - 1, mid;

c[nrt] = c[rt] + 1;
sum[nrt] = sum[rt] + val;
while (l < r) {
mid = (l + r) >> 1;
if (x <= mid) {
lson[nrt] = tot++;
rson[nrt] = rson[rt];
nrt = lson[nrt];
rt = lson[rt];
r = mid;
} else {
lson[nrt] = lson[rt];
rson[nrt] = tot++;
nrt = rson[nrt];
rt = rson[rt];
l = mid + 1;
}
c[nrt] = c[rt] + 1;
sum[nrt] = sum[rt] + val;
}

return ret;
}

int Query_kth(int urt, int vrt, int frt, int k) {
int l = 0, r = m - 1, mid;
int tmp;

while (l < r) {
mid = (l + r) >> 1;
tmp = c[lson[urt]] + c[lson[vrt]] - (c[lson[frt]] << 1);
if (tmp >= k) {
urt = lson[urt];
vrt = lson[vrt];
frt = lson[frt];
r = mid;
} else {
k -= tmp;
urt = rson[urt];
vrt = rson[vrt];
frt = rson[frt];
l = mid + 1;
}
}

return l;
}

int Query_Bound(int urt, int vrt, int frt, int delta) {
int l = 0, r = m - 1, mid;
int cc = 0, csum = 0;
int tc, tsum;
int ans = 0, tmp;

while (l < r) {
mid = (l + r) >> 1;
tc = c[lson[urt]] + c[lson[vrt]] - (c[lson[frt]] << 1);
tsum = sum[lson[urt]] + sum[lson[vrt]] - (sum[lson[frt]] << 1);
tmp = mid*(tc+cc)-(tsum+csum);
if (tmp <= delta)
ans = max(ans, mid);
if (mid*(tc+cc)-(tsum+csum) >= delta) {
urt = lson[urt];
vrt = lson[vrt];
frt = lson[frt];
r = mid;
} else {
urt = rson[urt];
vrt = rson[vrt];
frt = rson[frt];
cc += tc;
csum += tsum;
l = mid + 1;
}
}

return ans;
}

void addEdge(int u, int v, int c) {
E[l].v = v;
E[l].c = c;
E[l].nxt = head[u];
head[u] = l++;

E[l].v = u;
E[l].c = c;
E[l].nxt = head[v];
head[v] = l++;
}

void dfs(int u, int fa, int dep) {
int v, k;

V[++top] = u;
D[top] = dep;
beg[u] = top;

for (k=head[u]; k!=-1; k=E[k].nxt) {
v = E[k].v;
if (v == fa)
continue;
T[v] = Insert(T[u], E[k].c, E[k].c);
dfs(v, u, dep+1);
V[++top] = u;
D[top] = dep;
}
}

void Init_RMQ(int n) {
int i, j;

for (i=1; i<=n; ++i)
dp[0][i] = i;
for (j=1; (1<<j)<=n; ++j)
for (i=1; i+(1<<j)-1<=n; ++i)
if (D[dp[j-1][i]] < D[dp[j-1][i+(1<<(j-1))]])
dp[j][i] = dp[j-1][i];
else
dp[j][i] = dp[j-1][i+(1<<(j-1))];
}

int RMQ(int l, int r) {
if (l > r)
swap(l, r);

int k = 0;

while (1<<(k+1) <= r-l+1)
++k;

if (D[dp[k][l]] < D[dp[k][r-(1<<k)+1]])
return V[dp[k][l]];
else
return V[dp[k][r-(1<<k)+1]];
}

void solve() {
T[1] = Build(0, m - 1);
dfs(1, 0, 0);
Init_RMQ(top);

int u, v, k, a, b;
int lca;
int ans, tmp, org;

while (q--) {
scanf("%d %d %d %d %d", &u, &v, &k, &a, &b);
lca = RMQ(beg[u], beg[v]);
org = Query_kth(T[u], T[v], T[lca], 1);
#ifndef ONLINE_JUDGE
// printf("f = %d\n", lca);
#endif
if (a <= b) {
ans = org + k / a;
} else {
ans = org;
if (k >= a)
ans += 1 + (k-a)/b;
tmp = Query_Bound(T[u], T[v], T[lca], k/b);
#ifndef ONLINE_JUDGE
// printf("org = %d, ans = %d, bound = %d\n", org, ans, tmp);
#endif
ans = max(ans, tmp);
}
printf("%d\n", ans);
}
}

int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif

int t;
int u, v, c;

scanf("%d", &t);
rep(tt, 1, t+1) {
init();
scanf("%d %d", &n, &q);
rep(i, 1, n) {
scanf("%d %d %d", &u, &v, &c);
addEdge(u, v, c);
}
printf("Case #%d:\n", tt);
solve();
}

#ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif

return 0;
}


数据发生器。

from copy import deepcopy
from random import randint, shuffle
import shutil
import string

def GenDataIn():
with open("data.in", "w") as fout:
t = 10
bound = 10**4
fout.write("%d\n" % (t))
for tt in xrange(t):
n = randint(100, 200)
q = randint(100, 200)
fout.write("%d %d\n" % (n, q))
ust = [1]
vst = range(2, n+1)
for i in xrange(1, n):
idx = randint(0, len(ust)-1)
u = ust[idx]
idx = randint(0, len(vst)-1)
v = vst[idx]
ust.append(v)
vst.remove(v)
c = randint(0, bound-1)
fout.write("%d %d %d\n" % (u, v, c))
for i in xrange(q):
u = randint(1, n)
while True:
v = randint(1, n)
if v!=u:
break
k = randint(0, bound)
a = randint(1, bound)
b = randint(1, bound)
fout.write("%d %d %d %d %d\n" % (u, v, k, a, b))

def MovDataIn():
desFileName = "F:\eclipse_prj\workspace\hdoj\data.in"
shutil.copyfile("data.in", desFileName)

if __name__ == "__main__":
GenDataIn()
MovDataIn()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: