题目链接
You are given a tree, it’s root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i.
Input
Multiple cases (no more than 10), for each case:
The first line contains two integers n (0<n<=10^5) and p, representing this tree has n nodes, its root is p.
Following n-1 lines, each line has two integers, representing an edge in this tree.
The input terminates with two zeros.
Output
For each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.
Sample Input
15 7
7 10
7 1
7 9
7 3
7 4
10 14
14 2
14 13
9 11
9 6
6 5
6 8
3 15
3 12
0 0
Sample Output
0 0 0 0 0 1 6 0 3 1 0 0 0 2 0
题意:现在给你一棵树,每个节点有一个编号,现在这棵树以给出p为根节点,问每个节点的有多少子节点编号比它小。
题解:如果在树上处理,肯定会超时,现在我们先用DFS序将树转化成线性结构,用一个record数组来记录每个节点遍历的顺序。然后每个节点的有多少子节点编号比它小,就是在record数组中两个时间戳对应区间求该编号在区间内是第几大,这用主席树来维护就好了。
求大佬解释:为什么一样的代码C++过了,但是G++MLE了?
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int mod = 10007;
const int maxn = 1e5 + 5;
const int inf = 1e9;
const long long onf = 1e18;
#define me(a, b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI 3.14159265358979323846
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int n, p;
int cnt, tot,rt, head[maxn << 1];
int in[maxn], out[maxn], record[maxn];
int root[maxn],ls[maxn*40],rs[maxn*40],sum[maxn*40];
struct node {
int v, next;
} tree[maxn << 1];
void add_edge(int u, int v) {
tree[cnt].v = v;
tree[cnt].next = head[u];
head[u] = cnt++;
}
void DFS(int u, int fa) {///DFS序
in[u] = ++tot;
record[tot] = u;
for (int i = head[u]; i != -1; i = tree[i].next) {
int v = tree[i].v;
if (v == fa)
continue;
DFS(v, u);
}
out[u] = tot;
}
void push_date(int pre,int &node,int pos,int l,int r){
node=++rt;
ls[node]=ls[pre],rs[node]=rs[pre];
sum[node]=sum[pre]+1;
if(l==r)
return ;
int mid=(l+r)>>1;
if(pos<=mid)
push_date(ls[pre],ls[node],pos,l,mid);
else
push_date(rs[pre],rs[node],pos,mid+1,r);
}
int query(int pre,int node,int L,int R,int l,int r){///主席树求第几大
if(L>R)
return 0;
if(L<=l&&R>=r)
return sum[node]-sum[pre];
int mid=(l+r)>>1;
int ans=0;
if(L<=mid)
ans+=query(ls[pre],ls[node],L,R,l,mid);
if(R>mid)
ans+=query(rs[pre],rs[node],L,R,mid+1,r);
return ans;
}
void init() {
me(head, -1);
tot = cnt =rt= 0;
}
int main() {
while (scanf("%d%d", &n, &p)!=EOF){
init();
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
DFS(p, -1);
for(int i=1;i<=n;i++)
push_date(root[i-1],root[i],record[i],1,n);///按遍历顺序建树
for(int i=1;i<=n;i++){
int l=in[i],r=out[i];
int ans=query(root[l],root[r],1,i,1,n);
printf("%d%c",ans,i==n?'\n':' ');
}
}
return 0;
}