XJOI网上同步训练DAY3 T2
2016-06-27 16:14
316 查看
考试的时候已经想出来怎么做了,但是没有时间打了T_T
思路:我们考虑将询问以lim排序,然后树链剖分,把边作为线段树的节点,然后随着询问lim的增大,改变线段树中节点的信息,然后每次询问我们用树链剖分询问,复杂度是O(nlogn),又get一种新的树链剖分打法
#include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<cstring> struct node{ int x,y,lim,id; }q[200005]; int V[200005],dep[200005],t[200005],dfn[200005],num,n,m; struct Data{ int l,r,s,v; Data(){} Data(int a,int b,int c,int d):l(a),r(b),s(c),v(d){} }s1[800005],s2[800005]; Data operator +(Data a,Data b){ Data ret(a.l,b.r,a.s+b.s,a.v+b.v); if (a.r&&b.l) ret.v=a.v+b.v-V[a.r]-V[b.l]+V[a.r+b.l]; if (b.l==b.s) ret.r=a.r+b.s; if (a.l==a.s) ret.l=b.l+a.s; return ret; } int tot,go[200005],next[200005],first[200005]; int size[200005],son[200005],top[200005],fa[200005]; int ans[200005],val[200005]; int read(){ int t=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} return t*f; } void insert(int x,int y,int z){ tot++; go[tot]=y; next[tot]=first[x]; first[x]=tot; val[tot]=z; } void add(int x,int y,int z){ insert(x,y,z);insert(y,x,z); } bool cmp(node a,node b){ return a.lim<b.lim; } bool cmp1(int x,int y){ return val[x]<val[y]; } void build(int k,int l,int r){ if (l==r){ s1[k]=s2[k]=Data(1,1,1,V[1]); return; } int mid=(l+r)/2; build(k*2,l,mid); build(k*2+1,mid+1,r); s1[k]=s1[k*2]+s1[k*2+1]; s2[k]=s2[k*2+1]+s2[k*2]; } void dfs1(int x,int f){ size[x]=1; for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (pur!=f){ dep[pur]=dep[x]+1; t[++t[0]]=i; dfs1(pur,x); size[x]+=size[pur]; if (size[pur]>size[son[x]]) son[x]=pur; } } } void dfs2(int x,int f){ dfn[x]=++num; if (son[x]) top[son[x]]=top[x],dfs2(son[x],x); for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (pur==f||pur==son[x]) continue; top[pur]=pur; fa[pur]=x; dfs2(pur,x); } } void modify(int k,int l,int r,int pos){ if (l==r){ s1[k]=s2[k]=Data(0,0,1,0); return; } int mid=(l+r)/2; if (pos<=mid) modify(k*2,l,mid,pos); else modify(k*2+1,mid+1,r,pos); s1[k]=s1[k*2]+s1[k*2+1]; s2[k]=s2[k*2+1]+s2[k*2]; } Data ask1(int k,int l,int r,int x,int y){ if (l==x&&r==y){ return s1[k]; } int mid=(l+r)/2; if (y<=mid) return ask1(k*2,l,mid,x,y); else if (x>mid) return ask1(k*2+1,mid+1,r,x,y); else return ask1(k*2,l,mid,x,mid)+ask1(k*2+1,mid+1,r,mid+1,y); } Data ask2(int k,int l,int r,int x,int y){ if (l==x&&r==y){ return s2[k]; } int mid=(l+r)/2; if (y<=mid) return ask2(k*2,l,mid,x,y); else if (x>mid) return ask2(k*2+1,mid+1,r,x,y); else return ask2(k*2+1,mid+1,r,mid+1,y)+ask2(k*2,l,mid,x,mid); } int work(int x,int y){ Data ans1(0,0,0,0),ans2(0,0,0,0); while (top[x]!=top[y]){ if (dep[top[x]]<dep[top[y]]){ ans2=ask1(1,1,n,dfn[top[y]],dfn[y])+ans2; y=fa[top[y]]; }else{ ans1=ans1+ask2(1,1,n,dfn[top[x]],dfn[x]); x=fa[top[x]]; } } if (x!=y){ if (dep[x]<dep[y]){ ans2=ask1(1,1,n,dfn[son[x]],dfn[y])+ans2; }else{ ans1=ans1+ask2(1,1,n,dfn[son[y]],dfn[x]); } } return (ans1+ans2).v; } int main(){ freopen("tx.in","r",stdin); n=read(); for (int i=1;i<n;i++) V[i]=read(); for (int i=1;i<n;i++){ int x=read()+1,y=read()+1,v=read(); add(x,y,v); } m=read(); for (int i=1;i<=m;i++){ q[i].x=read()+1,q[i].y=read()+1,q[i].lim=read();q[i].id=i; } dfs1(1,0);dfs2(1,0); std::sort(q+1,q+1+m,cmp); std::sort(t+1,t+1+t[0],cmp1); int h=1;build(1,1,n); for (int i=1;i<=m;i++){ while (val[t[h]]<=q[i].lim&&h<=t[0]){ modify(1,1,n,dfn[go[t[h]]]); h++; } ans[q[i].id]=work(q[i].x,q[i].y); } for (int i=1;i<=m;i++) printf("%d\n",ans[i]); }
相关文章推荐
- ecstore2.0数据库词典
- activity不停重启的原因,不停执行oncreate()等生命周期
- mysql 中timestamp的问题
- 背包问题
- 浅谈测试驱动开发(TDD)
- ios开发中第三方登录遇到的问题
- Linux之进程等待
- 安装MySQL时,最后步骤start service出错的解决办法
- Python的Tornado框架的异步任务与AsyncHTTPClient
- Linux基础学习--1:linux内核与发行详解
- mysql 插入replace改变原有数据某些字段
- hdu 4530(数学)
- 机器学习结果统计-准确率、召回率,F1-score
- 让nginx支持pathinfo
- 实用技巧!教你从层次/色调/创意3个方面设计出酷炫网页
- 公司用到的一些 iOS 开源库和第三方组件
- dvwa csrf
- php echo字符串直接下载
- 从流程解析Nginx对 Native aio支持
- Androidn Notification的使用,解决找不到setLatestEventInfo方法