laekov

BZOJ1488 || POJ1741 Tree

据说是男人八题。


状态太差调了一节宝贵的晚自习,严重不开心。


异常裸的点分治。然后里面还是套的sbt。


卡空间比较丧病,不能开nlogn,要想办法开到n。其实就是找重心分治完再bfs一遍。最初没有写,所以mle爽,在poj上还显示的是re。


然后各种逗的错误调啊调。把代码调得怪丑。我还是naive啊。


#include <cstdio>

#include <cstring>

#include <algorithm>


using namespace std;


struct edge {

int t, v;

edge *next;

};


const int maxn = 40009;


int n, k, ans;

int d[maxn], tvis, vis[maxn], vd[maxn], sz[maxn], qu[maxn];

edge *ep, *head[maxn], elst[maxn * 2];


#define update(_p_) (sz[_p_]=sz[ls[_p_]]+sz[rs[_p_]]+1)


namespace sbt {

const int maxnd = maxn * 2;

const int balc = 5;

int nst[maxnd], tn;

int ls[maxnd], rs[maxnd], vl[maxnd], sz[maxnd];

inline void lRot(int& p) {

int q = rs[p];

rs[p] = ls[q];

ls[q] = p;

update(p);

update(q);

p = q;

}

inline void rRot(int& p) {

int q = ls[p];

ls[p] = rs[q];

rs[q] = p;

update(p);

update(q);

p = q;

}

void init() {

tn = 0;

sz[0] = 0;

for (int i = 1; i < maxnd; ++ i)

nst[tn ++] = i;

}

inline void ins(int& p, int v) {

if (!p) {

p = nst[-- tn];

ls[p] = 0;

rs[p] = 0;

sz[p] = 1;

vl[p] = v;

}

else {

++ sz[p];

if (v < vl[p]) {

ins(ls[p], v);

if (sz[ls[p]] > sz[rs[p]] + balc)

rRot(p);

}

else {

ins(rs[p], v);

if (sz[ls[p]] + balc < sz[rs[p]])

lRot(p);

}

}

}

inline int cntLower(int p, int v) {

if (!p)

return 0;

else if (v < vl[p])

return cntLower(ls[p], v);

else

return sz[ls[p]] + 1 + cntLower(rs[p], v);

}

void cntEach(int p, int q, int v) {

if (!p)

return;

ans += cntLower(q, v - vl[p]);

cntEach(ls[p], q, v);

cntEach(rs[p], q, v);

}

void insEach(int p, int& q, int a) {

if (!p)

return;

ins(q, vl[p] + a);

insEach(ls[p], q, a);

insEach(rs[p], q, a);

nst[tn ++] = p;

}

void rmv(int p) {

if (!p)

return;

nst[tn ++] = p;

rmv(ls[p]);

rmv(rs[p]);

}

};


inline void addEdge(int u, int v, int w) {

ep-> t = v;

ep-> v = w;

ep-> next = head[u];

head[u] = ep ++;

}


void getCore(int p0, int& ht) {

int hd = 0, tl = 1, mv;

++ tvis;

qu[hd] = p0;

vis[p0] = tvis;

d[p0] = 1;

while (hd < tl) {

int p = qu[hd ++];

for (edge* e = head[p]; e; e = e-> next)

if (!vd[e-> t] && vis[e-> t] < tvis) {

d[e-> t] = d[p] + 1;

vis[e-> t] = tvis;

qu[tl ++] = e-> t;

}

}

ht = qu[tl - 1];

mv = tl;

for (int i = tl - 1; i >= 0; -- i) {

int p = qu[i], ms = 0;

sz[p] = 1;

for (edge* e = head[p]; e; e = e-> next)

if (vis[e-> t] == tvis && d[e-> t] > d[p]) {

sz[p] += sz[e-> t];

if (ms < sz[e-> t])

ms = sz[e-> t];

}

if (max(ms, tl - sz[p]) < mv) {

mv = max(ms, tl - sz[p]);

ht = p;

}

}

}


void recoverTree(int p0, int dd, int& hr) {

int hd = 0, tl = 1;

qu[hd] = p0;

d[p0] = 0;

hr = 0;

while (hd < tl) {

int p = qu[hd ++];

-- vd[p];

sbt :: ins(hr, d[p]);

for (edge* e = head[p]; e; e = e-> next)

if (vd[e-> t] == dd) {

qu[tl ++] = e-> t;

d[e-> t] = d[p] + e-> v;

}

}

}


int calcTree(int p0, int d = 1) {

int ht, hr, rt = 0;

getCore(p0, ht);

   rt = 0;

sbt :: ins(rt, 0);

vd[ht] = d;

for (edge* e = head[ht]; e; e = e-> next)

if (!vd[e-> t]) {

int r = calcTree(e-> t, d + 1);

sbt :: cntEach(r, rt, k - e-> v);

sbt :: insEach(r, rt, e-> v);

}

sbt :: rmv(rt);

recoverTree(p0, d, hr);

return hr;

}


int sov() {

ep = elst;

memset(head, 0, sizeof(head));

memset(vis, 0, sizeof(vis));

memset(vd, 0, sizeof(vd));

scanf("%d", &n);

for (int i = 0; i < n - 1; ++ i) {

int u, v, w;

scanf("%d%d%d", &u, &v, &w);

addEdge(u, v, w);

addEdge(v, u, w);

}

scanf("%d", &k);

tvis = 0;

ans = 0;

int x = calcTree(1);

sbt :: rmv(x);

return ans;

}


int main() {

#ifndef ONLINE_JUDGE

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

#endif


sbt :: init();

ep = elst;

printf("%d\n", sov());

}



评论

© laekov | Powered by LOFTER