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 }

猜你喜欢

转载自www.cnblogs.com/blog-Dr-J/p/9458096.html