HDU
来源:互联网 发布:淘宝店铺首页1200 编辑:程序博客网 时间:2024/06/13 05:52
HDU - 5840 - This world need more Zhu
将询问分为
对于
对于向上的边,开始点
对于向下的边,开始点
可以直接从开始点向上/向下走,每次询问复杂度为
对于
对于一条链
对于向上的边
对于向下的边
对于每一个 dfs
序升序来排序,放到线段树上。这样对于一个询问,我们只需要访问一条链上模 dfs
序连续。一次询问复杂度是
因此总的复杂度是
将
#include<bits/stdc++.h>#define lson (rt<<1)#define rson (rt<<1|1)using namespace std;const int N=1e5+7;const int BLOCK=100;int n,a[N],ans[N],son[N],fa[N],top[N],sz[N],id[N],d[N],b[N],cnt,st[N],tp,mx[N<<2],L[BLOCK],R[BLOCK],tmp[N];vector<int> hs[BLOCK],adj[N];struct Query{ int u,v,k,down,lca,id;};vector<Query> q1[N],q2[BLOCK];inline int LCA(int u,int v){ while(top[u]!=top[v]) { if(d[top[u]]<d[top[v]]) swap(u,v); u=top[u]; u=fa[u]; } return d[u]<d[v]?u:v;}inline void init(){ memset(a,0,sizeof(a)); memset(ans,0,sizeof(ans)); top[1]=1; tp=cnt=0; memset(son,-1,sizeof(son)); for(int i=1;i<=n;++i) q1[i].clear(),adj[i].clear(); for(int i=0;i<BLOCK;++i) q2[i].clear();}void dfs1(int u,int deep,int father){ sz[u]=1;d[u]=deep;fa[u]=father; for(int v : adj[u]) { if(v==father) continue; dfs1(v,deep+1,u); sz[u]+=sz[v]; if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v; }}void dfs2(int u){ id[u]=++cnt; b[cnt]=u; if(son[u]!=-1) { top[son[u]]=top[u]; dfs2(son[u]); } for(int v : adj[u]) { if(v==fa[u]||v==son[u]) continue; top[v]=v; dfs2(v); }}void work_1(int u){ st[tp++]=u; for(Query & q : q1[u]) { int u=q.u,v=q.v,lca=q.lca,k=q.k,id=q.id,down=q.down; if(down) { int tmp=d[lca]+((d[lca]-d[u]-1)%k+k)%k; while(tmp<tp&&d[st[tmp]]<=d[v]) ans[id]=max(ans[id],a[st[tmp]]),tmp+=k; } else { int tmp=tp-k; while(tmp>=0&&d[st[tmp]]>=d[lca]) ans[id]=max(ans[id],a[st[tmp]]),tmp-=k; } } for(int v : adj[u]) { if(v==fa[u]) continue; work_1(v); } --tp;}inline void push_up(int rt){ mx[rt]=max(mx[lson],mx[rson]);}void build(int rt,int l,int r){ if(l==r) { mx[rt]=a[b[tmp[l]]];return ; } int m=(l+r)>>1; build(lson,l,m); build(rson,m+1,r); push_up(rt);}int query(int rt,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r) return mx[rt]; int m=(l+r)>>1; int res=0; if(ql<=m) res=max(res,query(lson,l,m,ql,qr)); if(qr>m) res=max(res,query(rson,m+1,r,ql,qr)); return res;}inline int cal(int l,int r,int k){ l=lower_bound(tmp+L[k],tmp+R[k]+1,l)-tmp; r=upper_bound(tmp+L[k],tmp+R[k]+1,r)-tmp-1; return l<=r?query(1,1,n,l,r):0;}inline void solve(int x,int u,int k,int id){ if(d[u]<d[x]) return ; while(top[u]!=top[x]) { ans[id]=max(ans[id],cal(::id[top[u]],::id[u],k)); u=fa[top[u]]; } ans[id]=max(ans[id],cal(::id[x],::id[u],k));}inline void work_2(int k){ for(int i=0;i<k;++i) hs[i].clear(); for(int i=1;i<=n;++i) hs[d[b[i]]%k].push_back(i); int tot=0; for(int i=0;i<k;++i) { L[i]=tot+1; for(int v : hs[i]) tmp[++tot]=v; R[i]=tot; } build(1,1,n); for(Query & q : q2[k]) { int u=q.u,v=q.v,k=q.k,lca=q.lca,id=q.id; solve(lca,u,(d[u]+1)%k,id); solve(lca,v,((2*d[lca]-d[u]-1)%k+k)%k,id); }}int main(){ int T,m; scanf("%d",&T); for(int kase=1;kase<=T;++kase) { scanf("%d%d",&n,&m); init(); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<n;++i) { int u,v; scanf("%d%d",&u,&v); adj[u].push_back(v); adj[v].push_back(u); } dfs1(1,0,1); dfs2(1); for(int i=0;i<m;++i) { int u,v,k; scanf("%d%d%d",&u,&v,&k); if(k<BLOCK) q2[k].push_back({u,v,k,1,LCA(u,v),i}); else { q1[u].push_back({u,v,k,0,LCA(u,v),i}); q1[v].push_back({u,v,k,1,LCA(u,v),i}); } } work_1(1); for(int i=0;i<BLOCK;++i) if(q2[i].size()) work_2(i); printf("Case #%d:\n",kase); for(int i=0;i<m;++i) printf("%d\n",ans[i]); } return 0;}
阅读全文
0 0
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- hdu
- hdu
- hdu
- HDU
- Robot Framework String库的常用方法
- 用oracle数据库做一份课表
- String、StringBuffer与StringBuilder之间区别
- java html转word!
- OC : NSFileHandle (文件内容操作)
- HDU
- appium通过图像识别技术opencv解决密码键盘的模拟输入密码问题
- 第八个Java程序,实现变量值的交换。
- Android studio安装应用失败(遇到的情况之一)
- jstl 格式化时间日期标签讲解
- jquery.ajax调用新浪/网易k线数据 具体操作ajax
- 关于各语言的求余,欢迎讨论。
- css布局 一行排几个元素
- 使用create-react-app创建项目