2018-8-10 模拟赛T3(可持久化线段树)
出题人说:正解离线按DFS序排序线段维护区间和
但是对于树上每个点都有一个区间和一个值,两个点之间求1~m的区间和,这不就是用可持久化线段树吗。
只不过这个线段树需要区间修改,不过不需要标记下传,询问时加起来就好了。
对于每一个节点x,建一个1~m的线段树版本
询问时,先求出u和v的lca和lca的父亲flca
询问在{u+v}和{lca,flca}的差集中的区间和就好了
可持久化数据结构耗费的空间是巨大的^_^
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long lnt; 6 struct pnt{ 7 int hd; 8 int a; 9 int b; 10 int oul; 11 int fa; 12 int dp; 13 lnt w; 14 int root; 15 }p[200000]; 16 struct ent{ 17 int twd; 18 int lst; 19 }e[1000000]; 20 struct tree{ 21 int l,r; 22 lnt val; 23 lnt laz; 24 }; 25 struct Traos{ 26 tree tr[8000000]; 27 int siz; 28 int ks; 29 lnt ansl; 30 void build(int l,int r,int &spc) 31 { 32 if(!spc) 33 spc=++siz; 34 if(l==r) 35 return ; 36 int md=(l+r)/2; 37 build(l,md,tr[spc].l); 38 build(md+1,r,tr[spc].r); 39 } 40 void updte(int &spc,int last,int ll,int rr,int l,int r,lnt v) 41 { 42 if(l>rr||r<ll) 43 return ; 44 spc=++siz; 45 tr[spc]=tr[last]; 46 if(ll<=l&&rr>=r) 47 { 48 tr[spc].val+=(lnt)(r-l+1)*v; 49 tr[spc].laz+=v; 50 return ; 51 } 52 tr[spc].val+=(lnt)(min(rr,r)-max(l,ll)+1)*v; 53 int mid=(l+r)/2; 54 updte(tr[spc].l,tr[last].l,ll,rr,l,mid,v); 55 updte(tr[spc].r,tr[last].r,ll,rr,mid+1,r,v); 56 return ; 57 } 58 lnt sumls(int spc1,int spc2,int ll,int rr,int l,int r) 59 { 60 if(l>rr||ll>r) 61 return 0ll; 62 if(ll<=l&&rr>=r) 63 return (lnt)(tr[spc2].val-tr[spc1].val); 64 int mid=(l+r)/2; 65 return (lnt)((lnt)(min(rr,r)-max(ll,l)+1)*(tr[spc2].laz-tr[spc1].laz))+sumls(tr[spc1].l,tr[spc2].l,ll,rr,l,mid)+sumls(tr[spc1].r,tr[spc2].r,ll,rr,mid+1,r); 66 67 } 68 }T; 69 int cnt; 70 int ont; 71 int n,m,q; 72 int ola[20][500000]; 73 int rt[100001]; 74 int lg[500000]; 75 void ade(int f,int t) 76 { 77 cnt++; 78 e[cnt].lst=p[f].hd; 79 e[cnt].twd=t; 80 p[f].hd=cnt; 81 } 82 void dfs(int x,int f) 83 { 84 p[x].fa=f; 85 p[x].dp=p[f].dp+1; 86 p[x].oul=++ont; 87 ola[0][ont]=x; 88 for(int i=p[x].hd;i;i=e[i].lst) 89 { 90 int to=e[i].twd; 91 if(to!=f) 92 { 93 dfs(to,x); 94 ola[0][++ont]=x; 95 } 96 } 97 } 98 int mxs(int a,int b) 99 { 100 return p[a].dp<p[b].dp?a:b; 101 } 102 void kls() 103 { 104 for(int i=1;i<=18;i++) 105 { 106 for(int j=1;j+(1<<i)-1<=ont;j++) 107 { 108 ola[i][j]=mxs(ola[i-1][j],ola[i-1][j+(1<<(i-1))]); 109 } 110 } 111 } 112 int lca(int a,int b) 113 { 114 if(p[a].oul>p[b].oul) 115 swap(a,b); 116 int lgg=lg[p[b].oul-p[a].oul+1]; 117 return mxs(ola[lgg][p[a].oul],ola[lgg][p[b].oul-(1<<lgg)+1]); 118 } 119 void fdfs(int x,int f) 120 { 121 p[x].root=++T.ks; 122 T.updte(rt[p[x].root],rt[p[f].root],p[x].a,p[x].b,1,m,p[x].w); 123 for(int i=p[x].hd;i;i=e[i].lst) 124 { 125 int to=e[i].twd; 126 if(to-f) 127 { 128 fdfs(to,x); 129 } 130 } 131 } 132 int main() 133 { 134 freopen("c.in","r",stdin); 135 freopen("c.out","w",stdout); 136 scanf("%d%d%d",&n,&m,&q); 137 for(int i=2;i<=3*n;i++) 138 { 139 lg[i]=lg[i/2]+1; 140 } 141 for(int i=1;i<n;i++) 142 { 143 int x,y; 144 scanf("%d%d",&x,&y); 145 ade(x,y); 146 ade(y,x); 147 } 148 for(int i=1;i<=n;i++) 149 { 150 scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].w); 151 p[i].a=min(p[i].a,p[i].b); 152 p[i].b=max(p[i].a,p[i].b); 153 } 154 dfs(1,0); 155 kls(); 156 T.build(1,m,rt[0]); 157 fdfs(1,0); 158 for(int i=1;i<=q;i++) 159 { 160 int u,v,l,r; 161 scanf("%d%d%d%d",&u,&v,&l,&r); 162 l=min(l,r); 163 r=max(l,r); 164 int la=lca(u,v); 165 lnt ans=0; 166 int fl=p[la].fa; 167 ans=T.sumls(rt[p[la].root],rt[p[u].root],l,r,1,m); 168 ans+=T.sumls(rt[p[fl].root],rt[p[v].root],l,r,1,m); 169 printf("%lld\n",ans); 170 } 171 return 0; 172 }