您的位置:首页 > 其它

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]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: