# BZOJ4012: [HNOI2015]开店【动态点分治】

## Input

b、A计算出 L和R，表示询问“在地方 u开店，面向妖怪的年龄区间为[L,R]的方

R=max(a%A,b%A)。对于第 2到第 Q行，假设前一行得到的方便值为 ans，那么当

R=max((a+ans)%A,(b+ans)%A)。

## Sample Input

10 10 10
0 0 7 2 1 4 7 7 7 9
1 2 270
2 3 217
1 4 326
2 5 361
4 6 116
3 7 38
1 8 800
6 9 210
7 10 278
8 9 8
2 8 0
9 3 1
8 0 8
4 2 7
9 7 3
4 7 0
2 2 7
3 2 1
2 3 4

1603
957
7161
9466
3232
5223
1879
1669
1282
0

## 思路

#include<bits/stdc++.h>

using namespace std;

int res = 0, w = 1; char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = -1, c = getchar();
while (isdigit(c)) res = (res << 1) + (res << 3) + c - '0', c = getchar();
return res * w;
}

typedef long long ll;
typedef pair<ll, int> pi;
const int N = 2e5 + 10;
const int LOG = 40;

struct Edge {
int v, w, nxt;
Edge(int v = 0, int w = 0, int nxt = 0): v(v), w(w), nxt(nxt) {}
} E[N << 1];
int n, q, A, num_age, age[N], pre[N];
char c[10];

void addedge(int u, int v, int w) {
}

namespace LCA {

struct Node {
int id, depth;
Node(int id = 0, int depth = 0): id(id), depth(depth) {}
bool operator < (const Node b) const {
return depth < b.depth;
}
} ST[N << 1][LOG];
int first[N], dep[N], log[N << 1], dist[N], len;

void dfs(int u, int fa) {
ST[++len][0] = Node(u, dep[u]);
first[u] = len;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa) continue;
dep[v] = dep[u] + 1;
dist[v] = dist[u] + E[i].w;
dfs(v, u);
ST[++len][0] = Node(u, dep[u]);
}
}

void init() {
dfs(1, 0);
log[1] = 0;
for (int i = 2; i <= len; i++) log[i] = log[i >> 1] + 1;
for (int j = 1; (1 << j) <= len; j++) {
for (int i = 1; i + (1 << j) - 1 <= len; i++) {
ST[i][j] = min(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
}
}
}

int getdis(int u, int v) {
if (first[u] < first[v]) swap(u, v);
int k = log[first[u] - first[v] + 1];
int lca = min(ST[first[v]][k], ST[first[u] - (1 << k) + 1][k]).id;
return dist[u] + dist[v] - (dist[lca] << 1);
}

}

namespace Segment_Tree {

int tot = 0, rt[N << 1], ls[(N * LOG) << 1], rs[(N * LOG) << 1];
ll val[(N * LOG) << 1], siz[(N * LOG) << 1];

void modify(int &t, int l, int r, int pos, int vl) {
if (!t) t =++tot;
val[t] += vl, siz[t]++;
if (l == r) return;
int mid = (l + r) >> 1;
if (pos <= mid) modify(ls[t], l, mid, pos, vl);
else modify(rs[t], mid + 1, r, pos, vl);
}

pi query(int t, int l, int r, int ql, int qr) {
if (!t) return pi(0ll, 0);
if (ql <= l && r <= qr) return pi(val[t], siz[t]);
int mid = (l + r) >> 1;
if (qr <= mid) return query(ls[t], l, mid, ql, qr);
else if (ql > mid) return query(rs[t], mid + 1, r, ql, qr);
else {
pi ansl = query(ls[t], l, mid, ql, mid);
pi ansr = query(rs[t], mid + 1, r, mid + 1, qr);
return  pi(ansl.first + ansr.first, ansl.second + ansr.second);
}
}

}

namespace Tree_Devide {

int father[N], siz[N], F[N], siz_all, root;
bool vis[N];

void getsiz(int u, int fa) {
siz[u] = 1;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa || vis[v]) continue;
getsiz(v, u);
siz[u] += siz[v];
}
}

void getroot(int u, int fa) {
F[u] = 0;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa || vis[v]) continue;
getroot(v, u);
F[u] = max(F[u], siz[v]);
}
F[u] = max(F[u], siz_all - siz[u]);
if (F[u] < F[root]) root = u;
}

void solve(int u, int fa) {
father[u] = fa;
vis[u] = 1;
getsiz(u, 0);
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (vis[v]) continue;
F[root = 0] = siz_all = siz[v];
getroot(v, 0);
solve(root, u);
}
}

void init() {
getsiz(1, 0);
F[root = 0] = siz_all = n;
getroot(1, 0);
solve(root, 0);
}

#define ID0(p) (p)
#define ID1(p) (p + n)

void modify_tree(int u) {
using namespace Segment_Tree;
modify(rt[ID0(u)], 1, num_age, age[u], 0);
for (int cur = u; father[cur]; cur = father[cur]) {
int dis = LCA::getdis(u, father[cur]);
modify(rt[ID0(father[cur])], 1, num_age, age[u], dis);
modify(rt[ID1(cur)], 1, num_age, age[u], dis);
}
}

ll query_tree(int u, int l, int r) {
using namespace Segment_Tree;
ll res = query(rt[ID0(u)], 1, num_age, l, r).first;
pi now;
for (int cur = u; father[cur]; cur = father[cur]) {
int dis = LCA::getdis(u, father[cur]);
now = query(rt[ID0(father[cur])], 1, num_age, l, r);
res += now.first + 1ll * dis * now.second;
now = query(rt[ID1(cur)], 1, num_age, l, r);
res -= now.first + 1ll * dis * now.second;
}
return res;
}

}

int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
for (int i = 1; i <= n; i++) {
}
sort(pre + 1, pre + n + 1);
num_age = unique(pre + 1, pre + n + 1) - pre - 1;
for (int i = 1; i <= n; i++) {
age[i] = lower_bound(pre + 1, pre + num_age + 1, age[i]) - pre;
}
for (int i = 1; i < n; i++) {
}
LCA::init();
Tree_Devide::init();
for (int i = 1; i <= n; i++) {
Tree_Devide::modify_tree(i);
}
ll lastans = 0;
while (q--) {
int u = read(), l = (read() % A + lastans % A) % A, r = (read() % A + lastans % A) % A;
if (l > r) swap(l, r);
l = lower_bound(pre + 1, pre + num_age + 1, l) - pre;
r = upper_bound(pre + 1, pre + num_age + 1, r) - pre - 1;
lastans = Tree_Devide::query_tree(u, l, r);
printf("%lld\n", lastans);
}
return 0;
}


vector+二分

#include<bits/stdc++.h>

using namespace std;

int res = 0, w = 1; char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = -1, c = getchar();
while (isdigit(c)) res = (res << 1) + (res << 3) + c - '0', c = getchar();
return res * w;
}

typedef long long ll;
typedef pair<int, ll> pi;
const int INF_of_int = 1e9;
const int N = 2e5 + 10;
const int LOG = 40;

struct Edge {
int v, w, nxt;
Edge(int v = 0, int w = 0, int nxt = 0): v(v), w(w), nxt(nxt) {}
} E[N << 1];
int n, q, A, age[N];

void addedge(int u, int v, int w) {
}

namespace LCA {

struct Node {
int id, depth;
Node(int id = 0, int depth = 0): id(id), depth(depth) {}
bool operator < (const Node b) const {
return depth < b.depth;
}
} ST[N << 1][LOG];
int first[N], dep[N], log[N << 1], dist[N], len;

void dfs(int u, int fa) {
ST[++len][0] = Node(u, dep[u]);
first[u] = len;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa) continue;
dep[v] = dep[u] + 1;
dist[v] = dist[u] + E[i].w;
dfs(v, u);
ST[++len][0] = Node(u, dep[u]);
}
}

void init() {
dfs(1, 0);
log[1] = 0;
for (int i = 2; i <= len; i++) log[i] = log[i >> 1] + 1;
for (int j = 1; (1 << j) <= len; j++) {
for (int i = 1; i + (1 << j) - 1 <= len; i++) {
ST[i][j] = min(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
}
}
}

int getdis(int u, int v) {
if (first[u] < first[v]) swap(u, v);
int k = log[first[u] - first[v] + 1];
int lca = min(ST[first[v]][k], ST[first[u] - (1 << k) + 1][k]).id;
return dist[u] + dist[v] - (dist[lca] << 1);
}

}

namespace Tree_Devide {

int father[N], siz[N], F[N], siz_all, root;
bool vis[N];
vector<pi> sum[2][N];

void getsiz(int u, int fa) {
siz[u] = 1;
sum[0][root].push_back(pi(age[u], LCA::getdis(u, root)));
sum[1][root].push_back(pi(age[u], LCA::getdis(u, father[root])));
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa || vis[v]) continue;
getsiz(v, u);
siz[u] += siz[v];
}
}

void getroot(int u, int fa) {
F[u] = 0;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa || vis[v]) continue;
getroot(v, u);
F[u] = max(F[u], siz[v]);
}
F[u] = max(F[u], siz_all - siz[u]);
if (F[u] < F[root]) root = u;
}

void solve(int u, int fa) {
father[u] = fa;
vis[u] = 1;
sum[0][u].push_back(pi(-INF_of_int, 0));
sum[1][u].push_back(pi(-INF_of_int, 0));
getsiz(u, 0);
sum[0][u].push_back(pi(INF_of_int + 1, 0));
sum[1][u].push_back(pi(INF_of_int + 1, 0));
sort(sum[0][u].begin(), sum[0][u].end());
sort(sum[1][u].begin(), sum[1][u].end());
int len;
len = sum[0][u].size();
for (int i = 1; i < len; i++) sum[0][u][i].second += sum[0][u][i - 1].second;
len = sum[1][u].size();
for (int i = 1; i < len; i++) sum[1][u][i].second += sum[1][u][i - 1].second;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (vis[v]) continue;
F[root = 0] = siz_all = siz[v];
getroot(v, 0);
solve(root, u);
}
}

void init() {
getsiz(1, 0);
F[root = 0] = siz_all = n;
getroot(1, 0);
solve(root, 0);
}

pi query(int u, int typ, int vl) {
int l = 1, r = sum[typ][u].size() - 1, res = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (sum[typ][u][mid].first <= vl) res = mid, l = mid + 1;
else r = mid - 1;
}
return pi(res, sum[typ][u][res].second);
}

pi query(int u, int typ, int l, int r) {
pi ansl = query(u, typ, l - 1);
pi ansr = query(u, typ, r);
return pi(ansr.first - ansl.first, ansr.second - ansl.second);
}

ll query_tree(int u, int l, int r) {
ll res = query(u, 0, l, r).second;
pi now;
for (int cur = u; father[cur]; cur = father[cur]) {
int dis = LCA::getdis(u, father[cur]);
now = query(father[cur], 0, l, r);
res += now.second + 1ll * dis * now.first;
now = query(cur, 1, l, r);
res -= now.second + 1ll * dis * now.first;
}
return res;
}

}

int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
for (int i = 1; i <= n; i++) age[i] = read();
for (int i = 1; i < n; i++) {
}
LCA::init();
Tree_Devide::init();
ll lastans = 0;
while (q--) {
int u = read(), l = (read() % A + lastans % A) % A, r = (read() % A + lastans % A) % A;
if (l > r) swap(l, r);
lastans = Tree_Devide::query_tree(u, l, r);
printf("%lld\n", lastans);
}
return 0;
}

posted @ 2018-12-02 17:11  Dream_maker_yk  阅读(185)  评论(0编辑  收藏  举报