SWERC2016 Performance Review

来源:互联网 发布:淘宝有什么好的男装店 编辑:程序博客网 时间:2024/06/11 06:20

OI时期曾用过dfs序,结果今天没想起来。。。。考场上yy树状数组特殊用法奇特姿势,然而没卵用,只能dfs序转成区间。一场比赛A 2题,哇我好弱啊。。

给你一棵树 每个结点有r,t值  现在求所有结点i的子树中的r值小于i点的r值的所有结点的t值之和。

dfs序遍历,记录每个点访问进去时的dfn,和出来时候的dfn就知道他的子树的区间了。然后按照rank的从小到大进行添加,因为必须是严格小于时能加上t,所以dep小的先加,这样他的子树中可能和他rank相同的点就不会影响他了。

#include<cstdio>#include<cstring>#include<algorithm>#define maxl 100010using namespace std;long long n,dfn,cnt,root;struct node{long long rnk,ti,ind,dep;}a[maxl];long long intime[maxl],outtime[maxl],ehead[maxl],ans[maxl],b[maxl];struct ed{long long nxt,to;} e[maxl];bool vis[maxl];void dfs(long long u,long long de){long long v;intime[u]=++dfn;vis[u]=true;a[u].dep=de;for(long long i=ehead[u];i;i=e[i].nxt){v=e[i].to;if(!vis[v])dfs(v,de+1);}outtime[u]=dfn;}void prework(){long long fa;dfn=0;cnt=0;memset(ehead,0,sizeof(ehead));for(long long i=1;i<=n;i++){scanf("%I64d%I64d%I64d",&fa,&a[i].rnk,&a[i].ti);a[i].ind=i;if(fa>0)e[++cnt].to=i,e[cnt].nxt=ehead[fa],ehead[fa]=cnt;elseroot=i;}memset(vis,false,sizeof(vis));dfs(root,1);}bool cmp(const node &a,const node &b){if(a.rnk==b.rnk)return a.dep<b.dep;elsereturn a.rnk<b.rnk;}long long sum(long long i){long long s=0;while(i){s+=b[i];i-=i&-i;}return s;}void add(long long i,long long x){while(i<maxl){b[i]+=x;i+=i&-i;}}void mainwork(){memset(ans,0,sizeof(ans));memset(b,0,sizeof(b));sort(a+1,a+1+n,cmp);long long l,r;for(long long i=1;i<=n;i++){l=intime[a[i].ind];r=outtime[a[i].ind];ans[a[i].ind]+=sum(r)-sum(l-1);add(l,a[i].ti);}}void print(){for(long long i=1;i<=n;i++)printf("%I64d\n",ans[i]);}int main(){//freopen("in.in","r",stdin);//freopen("out.out","w",stdout);while(~scanf("%I64d",&n)){prework();mainwork();print();}return 0;}


原创粉丝点击