日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

NOIP2016天天爱跑步

發(fā)布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NOIP2016天天爱跑步 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

NOIP2016天天愛跑步

這題一看顯然lca+樹上差分,但是因為有w的限制不能直接加,所以考慮權(quán)值線段樹合并,

每個選手的起點終點對于不同的節(jié)點的影響是不同的,這就非常麻煩了,但是可以發(fā)現(xiàn)無論如何他的深度是固定的,而對于一個節(jié)點i,能使他+1有如下兩種情況:

1.dep[x]=dep[i]-w[i]

2.dep[x]=dep[i]+w[i]

于是對于一組s,t,求出他們的lca將路徑分為兩段,給s的dep[s]值加1,fa[lca]減1,t的2*dep[lca]-dep[s]加1,lca減1,

最后dfs線段樹合并,對于一個節(jié)點x,查詢對應(yīng)線段樹中dep[x]-w[x]+dep[x]+w[x]的個數(shù),注意如果w[x]是0要除2(因為多加了一遍)。

有了“雨天的尾巴”的經(jīng)驗,這道題代碼還是很好調(diào)的。

?

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
struct edge
{int u,v,nxt;#define u(x) ed[x].u#define v(x) ed[x].v#define n(x) ed[x].nxt
}ed[300010];
int first[300010],num_e;
#define f(x) first[x]
int n,m,root;
int dep[300010],du[300010];
struct tree
{int ls,rs,l,r,sum;#define ls(x)  tr[x].ls#define rs(x)  tr[x].rs#define l(x)   tr[x].l#define r(x)   tr[x].r#define sum(x) tr[x].sum 
}tr[10000010];
int cnt,T[300010];
void add(int &x,int y,int z,int l,int r)
{     if(!x){x=++cnt;l(x)=l,r(x)=r;}if(l==r){sum(x)+=z;return;}int mid=(l(x)+r(x))>>1;if(y<=mid)add(ls(x),y,z,l,mid);else      add(rs(x),y,z,mid+1,r);sum(x)=0;if(ls(x))sum(x)+=sum(ls(x));if(rs(x))sum(x)+=sum(rs(x));
}
int merge(int x,int y,int l,int r)
{if(!x||!y)return x+y;if(l==r){sum(x)+=sum(y);return x;}int mid=(l+r)>>1;ls(x)=merge(ls(x),ls(y),l,mid);rs(x)=merge(rs(x),rs(y),mid+1,r);sum(x)=sum(ls(x))+sum(rs(x));return x;
}
int ask(int x,int val,int l,int r)
{if(l==r){return sum(x);}int mid=(l+r)>>1;if(val<=mid)return ask(ls(x),val,l,mid);else        return ask(rs(x),val,mid+1,r);
}
int f[300010][21];
int LCA(int x,int y)
{if(x==y)return x;if(dep[x]>dep[y])swap(x,y);while(dep[x]<dep[y])for(int i=0;;i++)if(dep[f[y][i]]<dep[x]){y=f[y][i-1];break;}if(x==y)return x;while(f[x][0]!=f[y][0])for(int i=0;;i++)if(f[x][i]==f[y][i]){x=f[x][i-1],y=f[y][i-1];break;}return f[x][0];
}
void dfs(int x,int de,int fa)
{dep[x]=de;f[x][0]=fa;for(int i=f(x);i;i=n(i))dfs(v(i),de+1,x);
}
int ans[300010],w[300010];
void dfs2(int x)
{for(int i=f(x);i;i=n(i)){dfs2(v(i));T[x]=merge(T[x],T[v(i)],-n-1,n+1);}int t1=ask(T[x],dep[x]+w[x],-n-1,n+1),t2=ask(T[x],dep[x]-w[x],-n-1,n+1);ans[x]=t1+t2;if(!w[x])ans[x]-=t1;
}
inline void add_e(int u,int v);
signed main()
{
//    freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);int u,v;for(int i=1;i<n;i++){scanf("%d%d",&u,&v);add_e(u,v);du[v]++;}for(int i=1;i<=n;i++)scanf("%d",&w[i]);for(int i=1;i<=n;i++)if(!du[i]){root=i;break;}dfs(root,1,0);for(int i=1;i<=20;i++)for(int j=1;j<=n;j++)f[j][i]=f[f[j][i-1]][i-1];int s,t;for(int i=1;i<=m;i++){scanf("%d%d",&s,&t);int lca=LCA(s,t);add(T[s],dep[s],1,-n-1,n+1);if(lca!=root){add(T[f[lca][0]],dep[s],-1,-n-1,n+1);}add(T[t],2*dep[lca]-dep[s],1,-n-1,n+1);add(T[lca],2*dep[lca]-dep[s],-1,-n-1,n+1);}dfs2(root);printf("%d",ans[1]);for(int i=2;i<=n;i++)printf(" %d",ans[i]);
}
inline void add_e(int u,int v)
{++num_e;u(num_e)=u;v(num_e)=v;n(num_e)=f(u);f(u)=num_e;
}
View Code

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/Al-Ca/p/11179295.html

總結(jié)

以上是生活随笔為你收集整理的NOIP2016天天爱跑步的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。