Codeforces Round #381 (Div. 2) D. Alyona and a tree

来源:互联网 发布:怎么看淘宝店铺的销量 编辑:程序博客网 时间:2024/06/11 21:14

主要是运用树状数组快速区间求和,还有dfs求距离,记录点的顺序,该点的子树最远的叶子;


#include<bits/stdc++.h>using namespace std;#define pb(a) push_back(a)#define LL long longconst int maxn = 2e5+5;int a[maxn],in[maxn],out[maxn],c[maxn],ans[maxn];  //a-每个点的值,in-dfs该点的顺序,out-该点的子树最远的叶子LL dis[maxn]; //每个点到根的距离vector<int> g[maxn],w[maxn];  //g-建树,w-每条边的值int n,ord = 0;struct node {int tp,id;LL v;} b[maxn*2];bool cmp(node a,node b) {if(a.v == b.v) return a.tp < b.tp;return a.v < b.v;}void dfs(int x,LL d) {  //dfs in-标记每个点遍历的顺序,out-该点的子树最远的叶子,dis-该点到根节点的距离dis[x] = d;in[x] = ++ord;for(int i = 0;i < g[x].size();i++) {dfs(g[x][i],d+w[x][i]);}out[x] = ord;}void add(int x) {while(x <= n) {c[x]++;x += x&-x; //lowbit直接写在函数里面,看起来简洁些}}int query(int x) {int ans = 0;while(x) {ans += c[x];x -= x&-x;}return ans;}int main() {scanf("%d",&n);for(int i = 1;i <= n;i++) scanf("%d",&a[i]);for(int i = 2;i <= n;i++) {int u,v;scanf("%d%d",&u,&v);g[u].pb(i);w[u].pb(v);}dfs(1,0);int cnt = 0;for(int i = 1;i <= n;i++) {b[++cnt] = (node){1,i,dis[i]-a[i]};b[++cnt] = (node){2,i,dis[i]};}//for(int i = 1;i <= cnt;i++) printf("%d  %d  %I64d\n",b[i].tp,b[i].id,b[i].v);sort(b+1,b+1+cnt,cmp);memset(c,0,sizeof(c));for(int i = 1;i <= cnt;i++) {if(b[i].tp == 1) add(in[b[i].id]);else {ans[b[i].id] = query(out[b[i].id]) - query(in[b[i].id] - 1); }}for(int i = 1;i <= n;i++)printf("%d ",ans[i]-1);  //得到的答案包含它本身,所以要减一puts("");}


0 0
原创粉丝点击