XJOI网上同步训练DAY3 T2
考试的时候已经想出来怎么做了,但是没有时间打了T_T
思路:我们考虑将询问以lim排序,然后树链剖分,把边作为线段树的节点,然后随着询问lim的增大,改变线段树中节点的信息,然后每次询问我们用树链剖分询问,复杂度是O(nlogn),又get一种新的树链剖分打法
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstring> 6 struct node{ 7 int x,y,lim,id; 8 }q[200005]; 9 int V[200005],dep[200005],t[200005],dfn[200005],num,n,m; 10 struct Data{ 11 int l,r,s,v; 12 Data(){} 13 Data(int a,int b,int c,int d):l(a),r(b),s(c),v(d){} 14 }s1[800005],s2[800005]; 15 Data operator +(Data a,Data b){ 16 Data ret(a.l,b.r,a.s+b.s,a.v+b.v); 17 if (a.r&&b.l) ret.v=a.v+b.v-V[a.r]-V[b.l]+V[a.r+b.l]; 18 if (b.l==b.s) ret.r=a.r+b.s; 19 if (a.l==a.s) ret.l=b.l+a.s; 20 return ret; 21 } 22 int tot,go[200005],next[200005],first[200005]; 23 int size[200005],son[200005],top[200005],fa[200005]; 24 int ans[200005],val[200005]; 25 int read(){ 26 int t=0,f=1;char ch=getchar(); 27 while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} 28 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 29 return t*f; 30 } 31 void insert(int x,int y,int z){ 32 tot++; 33 go[tot]=y; 34 next[tot]=first[x]; 35 first[x]=tot; 36 val[tot]=z; 37 } 38 void add(int x,int y,int z){ 39 insert(x,y,z);insert(y,x,z); 40 } 41 bool cmp(node a,node b){ 42 return a.lim<b.lim; 43 } 44 bool cmp1(int x,int y){ 45 return val[x]<val[y]; 46 } 47 void build(int k,int l,int r){ 48 if (l==r){ 49 s1[k]=s2[k]=Data(1,1,1,V[1]); 50 return; 51 } 52 int mid=(l+r)/2; 53 build(k*2,l,mid); 54 build(k*2+1,mid+1,r); 55 s1[k]=s1[k*2]+s1[k*2+1]; 56 s2[k]=s2[k*2+1]+s2[k*2]; 57 } 58 void dfs1(int x,int f){ 59 size[x]=1; 60 for (int i=first[x];i;i=next[i]){ 61 int pur=go[i]; 62 if (pur!=f){ 63 dep[pur]=dep[x]+1; 64 t[++t[0]]=i; 65 dfs1(pur,x); 66 size[x]+=size[pur]; 67 if (size[pur]>size[son[x]]) son[x]=pur; 68 } 69 } 70 } 71 void dfs2(int x,int f){ 72 dfn[x]=++num; 73 if (son[x]) top[son[x]]=top[x],dfs2(son[x],x); 74 for (int i=first[x];i;i=next[i]){ 75 int pur=go[i]; 76 if (pur==f||pur==son[x]) continue; 77 top[pur]=pur; 78 fa[pur]=x; 79 dfs2(pur,x); 80 } 81 } 82 void modify(int k,int l,int r,int pos){ 83 if (l==r){ 84 s1[k]=s2[k]=Data(0,0,1,0); 85 return; 86 } 87 int mid=(l+r)/2; 88 if (pos<=mid) modify(k*2,l,mid,pos); 89 else modify(k*2+1,mid+1,r,pos); 90 s1[k]=s1[k*2]+s1[k*2+1]; 91 s2[k]=s2[k*2+1]+s2[k*2]; 92 } 93 Data ask1(int k,int l,int r,int x,int y){ 94 if (l==x&&r==y){ 95 return s1[k]; 96 } 97 int mid=(l+r)/2; 98 if (y<=mid) return ask1(k*2,l,mid,x,y); 99 else 100 if (x>mid) return ask1(k*2+1,mid+1,r,x,y); 101 else return ask1(k*2,l,mid,x,mid)+ask1(k*2+1,mid+1,r,mid+1,y); 102 } 103 Data ask2(int k,int l,int r,int x,int y){ 104 if (l==x&&r==y){ 105 return s2[k]; 106 } 107 int mid=(l+r)/2; 108 if (y<=mid) return ask2(k*2,l,mid,x,y); 109 else 110 if (x>mid) return ask2(k*2+1,mid+1,r,x,y); 111 else return ask2(k*2+1,mid+1,r,mid+1,y)+ask2(k*2,l,mid,x,mid); 112 } 113 int work(int x,int y){ 114 Data ans1(0,0,0,0),ans2(0,0,0,0); 115 while (top[x]!=top[y]){ 116 if (dep[top[x]]<dep[top[y]]){ 117 ans2=ask1(1,1,n,dfn[top[y]],dfn[y])+ans2; 118 y=fa[top[y]]; 119 }else{ 120 ans1=ans1+ask2(1,1,n,dfn[top[x]],dfn[x]); 121 x=fa[top[x]]; 122 } 123 } 124 if (x!=y){ 125 if (dep[x]<dep[y]){ 126 ans2=ask1(1,1,n,dfn[son[x]],dfn[y])+ans2; 127 }else{ 128 ans1=ans1+ask2(1,1,n,dfn[son[y]],dfn[x]); 129 } 130 } 131 return (ans1+ans2).v; 132 } 133 int main(){ 134 freopen("tx.in","r",stdin); 135 n=read(); 136 for (int i=1;i<n;i++) V[i]=read(); 137 for (int i=1;i<n;i++){ 138 int x=read()+1,y=read()+1,v=read(); 139 add(x,y,v); 140 } 141 m=read(); 142 for (int i=1;i<=m;i++){ 143 q[i].x=read()+1,q[i].y=read()+1,q[i].lim=read();q[i].id=i; 144 } 145 dfs1(1,0);dfs2(1,0); 146 std::sort(q+1,q+1+m,cmp); 147 std::sort(t+1,t+1+t[0],cmp1); 148 int h=1;build(1,1,n); 149 for (int i=1;i<=m;i++){ 150 while (val[t[h]]<=q[i].lim&&h<=t[0]){ 151 modify(1,1,n,dfn[go[t[h]]]); 152 h++; 153 } 154 ans[q[i].id]=work(q[i].x,q[i].y); 155 } 156 for (int i=1;i<=m;i++) printf("%d\n",ans[i]); 157 }