鏈接:https://ac.nowcoder.com/acm/contest/888/I
來源:牛客網
題目描述
Gromah and LZR are transfered to a forest, maybe it is the inner world of the great tomb. Initially, there are nn_{}n rooted trees numbered from 11_{}1 to nn_{}n with size 11_{}1 in the forest. For each tree, the only node is the root and labeled with 11_{}1.
After a while, here comes a farmer, and the farmer gives them mm_{}m planting tasks, each can be described by a tuple (u,v,l,r)(u,v,l,r)_{}(u,v,l,r), which means to add a labeled node vv_{}v for all trees numbered from ll_{}l to rr_{}r, and their parent nodes are the nodes labeled with uu_{}u for each tree.
After finishing the planting tasks one by one, the farmer will give them qq_{}q querying tasks, each can be described by a tuple (x,l,r)(x,l,r)_{}(x,l,r), which means to query the sum of sizes of subtrees whose roots are the nodes labeled with xx_{}x among the trees numbered from ll_{}l to rr_{}r. Specially, if there isn't a node labeled with xx_{}x in a tree, the size of subtree xx_{}x is regarded as 00_{}0.
If they complete all tasks perfectly, the farmer will help them pass the final level.
Please help them handle these tasks.
輸入描述:
The first line contains two positive integers n,mn,m_{}n,m, denoting the number of trees in the inner world and the number of planting tasks.
Following mm_{}m lines each contains four positive integers u,v,l,ru,v,l,r_{}u,v,l,r, denoting a planting task (u,v,l,r)(u,v,l,r)_{}(u,v,l,r).
The next line contains one positive integer qq_{}q, denoting the number of querying tasks.
Following qq_{}q lines each contains four positive integers x,l,rx,l,r_{}x,l,r, denoting a querying task (x,l,r)(x,l,r)_{}(x,l,r).
1≤n,m,q≤300000,1≤u,x≤m+1,2≤v≤m+1,1≤l≤r≤n1\le n,m,q \le 300000, 1 \le u,x \le m + 1, 2 \le v \le m + 1, 1 \le l \le r \le n1≤n,m,q≤300000,1≤u,x≤m+1,2≤v≤m+1,1≤l≤r≤n
For each planting task, It is guaranteed that the label vv_{}v is unique among all vv_{}vs, and the trees numbered from ll_{}l to rr_{}r all have a node labeled with uu_{}u right before handling this task.
輸出描述:
Output qq_{}q lines, each contains one non-negative integer denoting the answer to corresponding query task.
示例1
輸入
4 3
1 2 1 2
1 3 2 4
3 4 2 3
2
1 1 4
3 1 4
輸出
11
5
說明
Four trees are 1-2, 1(-2)-3-4, 1-3-4, 1-3.
In the four trees, sizes of subtrees 1 are 2,4,3,2, so the answer to the first query task is 2+4+3+2=11, while the sizes of subtrees 3 are 0,2,2,1 and the answer to the second query task is 0+2+2+1=5.
有n棵樹,有m個操作,每次操作將l,r區間內的u節點上加一個v,保證每次操作u必定存在
然後有q個詢問,每次問x,l,r,求l,r樹木區間內的x的子樹的數量和。
因爲題目保證v不一樣的,所以我們先將所有的操作當成一棵樹的操作,進行dfs序,獲得父子樹關係。然後按照dfs序列遍歷一邊。每次到一個點,用線段樹在區間l,r加上一,這樣我們要求某一個節點x的子樹在l,r區間內的子節點數量和,就相當於rt[x]時的l,r區間總和減去lt[x]時的l,r區間總和就好了。不明白的私聊留言即可。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 300005;
int n, m, L[maxn], R[maxn], cnt = 0;
int pos[maxn], lt[maxn], rt[maxn];
LL c[maxn * 4], lazy[maxn * 4];
vector<int>G[maxn];
struct node { int p, l, r; };
vector<node>q[maxn];
LL ans[maxn];
void dfs(int u) {
pos[lt[u] = ++cnt] = u;
for (auto v : G[u])dfs(v);
rt[u] = cnt;
}
void push_down(int x, int l, int r) {
int mid = (l + r) / 2;
c[x << 1] += lazy[x] * (mid - l + 1);
c[x << 1 | 1] += lazy[x] * (r - mid);
lazy[x << 1] += lazy[x];
lazy[x << 1 | 1] += lazy[x];
lazy[x] = 0;
}
void update(int x, int l, int r, int left, int right) {
if (left <= l && right >= r) {
c[x] += r - l + 1;
lazy[x] += 1;
return;
}
push_down(x, l, r);
int mid = (l + r) / 2;
if (left <= mid)
update(x << 1, l, mid, left, right);
if (right > mid)
update(x << 1 | 1, mid + 1, r, left, right);
c[x] = c[x << 1] + c[x << 1 | 1];
}
LL query(int x, int l, int r, int left, int right) {
if (left <= l && right >= r) return c[x];
push_down(x, l, r);
int mid = (l + r) / 2;
LL ans = 0;
if (left <= mid)
ans += query(x << 1, l, mid, left, right);
if (right > mid)
ans += query(x << 1 | 1, mid + 1, r, left, right);
return ans;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v, l, r;
cin >> u >> v >> l >> r;
G[u].push_back(v);
L[v] = l; R[v] = r;
}
L[1] = 1; R[1] = n;
dfs(1);
int qu; cin >> qu;
for (int i = 1; i <= qu; i++) {
int x, l, r;
cin >> x >> l >> r;
q[lt[x] - 1].push_back(node{ -i,l,r });
q[rt[x]].push_back(node{ i,l,r });
}
for (int i = 1; i <= cnt; i++) {//按dfs序列遍歷
update(1, 1, n, L[pos[i]], R[pos[i]]);
for (auto v : q[i]) {
int t = abs(v.p), op = v.p / t;
ans[t] += query(1, 1, n, v.l, v.r) * op;
}
}
for (int i = 1; i <= qu; i++)
printf("%lld\n", ans[i]);
return 0;
}