[luogu7434]Heavy Command Cruiser

对于叶子$x$,注意到$x$向下的射线仅是用于划分区域,其权值$d_{x}$可以直接记在$w_{x}$上(取$\min$)

定义$w'_{x}$为$x$向上的边(特别的,$x=1$时即1向上的射线)两侧的区域在对偶图中的最短路,考虑如何求——

称某区域在$x$的子树内当且仅当其相邻的两个叶子均在$x$子树内,并对路径分类讨论:

1.路径经过的区域(除起点和终点外)均在$x$子树内,这种情况的转移即$w'_{x}=\min(\sum_{son是x的儿子}w'_{son},w_{x})$

2.路径经过的区域均不在$x$子树内,这种情况的转移即$w'_{x}=\min(\sum_{bro是x的兄弟}w'_{bro}+w'_{fa_{x}},w'_{x})$

进一步的,不妨用$w'_{x}$代替$w_{x}$,进而即区域间的最短路经过相邻的区域必然直接使用对应的边

回到原问题,结合上述性质,不难发现经过的所有区域均是$u$到$v$路径上两侧的区域

令$f_{k,i,0/1,0/1}$表示从$k$向上的边左/右侧到$k$的$2^{i}$次祖先向上的边左/右侧的最短路,即可倍增转移

由于询问次数较多,需要通过长链剖分+sqrt tree做到$o(n\log n+q)$

(下面的代码并没有做上述优化,仅能得到20分)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 500005
  4 #define ll long long
  5 struct Data{
  6     int a[2][2];
  7     Data(int p=0x3f3f3f3f){
  8         a[0][0]=a[0][1]=a[1][0]=a[1][1]=p;
  9     }
 10     int get_min(){
 11         return min(min(a[0][0],a[0][1]),min(a[1][0],a[1][1]));
 12     }
 13 }f[N][20];
 14 vector<int>v[N];
 15 int n,q,x,y,ans,ans1,w[N],dep[N],sum[N],fa[N][20];
 16 ll ans2;
 17 namespace GenHelper{
 18     unsigned z1,z2,z3,z4,b;
 19     unsigned rand_(){
 20         b=((z1<<6)^z1)>>13;
 21         z1=((z1&4294967294U)<<18)^b;
 22         b=((z2<<2)^z2)>>27;
 23         z2=((z2&4294967288U)<<2)^b;
 24         b=((z3<<13)^z3)>>21;
 25         z3=((z3&4294967280U)<<7)^b;
 26         b=((z4<<3)^z4)>>12;
 27         z4=((z4&4294967168U)<<13)^b;
 28         return (z1^z2^z3^z4);
 29     }
 30 };
 31 void srand(unsigned x){
 32     using namespace GenHelper;
 33     z1=x;z2=(~x)^0x233333333U;z3=x^0x1234598766U;z4=(~x)+51;
 34 }
 35 int Read(){
 36     using namespace GenHelper;
 37     int a=rand_()&32767;
 38     int b=rand_()&32767;
 39     return a*32768+b;
 40 }
 41 int read(){
 42     int x=0;
 43     char c=getchar();
 44     while ((c<'0')||(c>'9'))c=getchar();
 45     while ((c>='0')&&(c<='9')){
 46         x=x*10+c-'0';
 47         c=getchar();
 48     }
 49     return x;
 50 }
 51 Data merge(Data x,Data y){
 52     Data ans;
 53     ans.a[0][0]=min(x.a[0][0]+y.a[0][0],x.a[0][1]+y.a[1][0]);
 54     ans.a[0][1]=min(x.a[0][0]+y.a[0][1],x.a[0][1]+y.a[1][1]);
 55     ans.a[1][0]=min(x.a[1][0]+y.a[0][0],x.a[1][1]+y.a[1][0]);
 56     ans.a[1][1]=min(x.a[1][0]+y.a[0][1],x.a[1][1]+y.a[1][1]);
 57     return ans;
 58 }
 59 void dfs1(int k){
 60     int s=0;
 61     for(int i=0;i<v[k].size();i++)dfs1(v[k][i]),s+=w[v[k][i]];
 62     if (!v[k].empty())w[k]=min(w[k],s);
 63 }
 64 void dfs2(int k){
 65     int s=w[k];
 66     for(int i=0;i<v[k].size();i++)s+=w[v[k][i]];
 67     for(int i=0;i<v[k].size();i++){
 68         w[v[k][i]]=min(w[v[k][i]],s-w[v[k][i]]);
 69         dfs2(v[k][i]);
 70     }
 71 }
 72 void dfs(int k,int s){
 73     dep[k]=s;
 74     for(int i=1;i<20;i++){
 75         fa[k][i]=fa[fa[k][i-1]][i-1];
 76         f[k][i]=merge(f[k][i-1],f[fa[k][i-1]][i-1]);
 77     }
 78     if (v[k].empty())return;
 79     sum[v[k][0]]=w[v[k][0]];
 80     for(int i=1;i<v[k].size();i++)sum[v[k][i]]=sum[v[k][i-1]]+w[v[k][i]];
 81     for(int i=0;i<v[k].size();i++){
 82         int l=0,r=sum[v[k].back()]-sum[v[k][i]];
 83         if (i)l=sum[v[k][i-1]];
 84         f[v[k][i]][0].a[0][0]=min(l,r+w[v[k][i]]+w[k]);
 85         f[v[k][i]][0].a[0][1]=min(l+w[k],r+w[v[k][i]]);
 86         f[v[k][i]][0].a[1][0]=min(l+w[v[k][i]],r+w[k]);
 87         f[v[k][i]][0].a[1][1]=min(l+w[v[k][i]]+w[k],r);
 88         dfs(v[k][i],s+1);
 89     }
 90 }
 91 int calc(int x,int y){
 92     if (x==y)return 0;
 93     if (dep[x]<dep[y])swap(x,y);
 94     Data ans1(0),ans2(0);
 95     ans1.a[0][1]=ans1.a[1][0]=w[x];
 96     ans2.a[0][1]=ans2.a[1][0]=w[y];
 97     for(int i=19;i>=0;i--)
 98         if (dep[fa[x][i]]>dep[y]){
 99             ans1=merge(ans1,f[x][i]);
100             x=fa[x][i];
101         }
102     if (fa[x][0]==y)return ans1.get_min();
103     if (dep[x]>dep[y])ans1=merge(ans1,f[x][0]),x=fa[x][0];
104     for(int i=19;i>=0;i--)
105         if (fa[x][i]!=fa[y][i]){
106             ans1=merge(ans1,f[x][i]),ans2=merge(ans2,f[y][i]);
107             x=fa[x][i],y=fa[y][i];
108         }
109     if (x>y)swap(x,y),swap(ans1,ans2);
110     int z=fa[x][0],S=w[z]+sum[v[z].back()];
111     int lx=min(ans1.a[0][0],ans1.a[1][0]),rx=min(ans1.a[0][1],ans1.a[1][1]);
112     int ly=min(ans2.a[0][0],ans2.a[1][0]),ry=min(ans2.a[0][1],ans2.a[1][1]);
113     return min(lx+ry+S-(sum[y]-sum[x]+w[x]),ly+rx+(sum[y]-sum[x]-w[y]));
114 }
115 int main(){
116     n=read(),q=read(),srand(read());
117     for(int i=2;i<=n;i++){
118         x=read(),w[i]=read();
119         fa[i][0]=x,v[x].push_back(i);
120     }
121     w[1]=read();
122     for(int i=1;i<=n;i++)
123         if (v[i].empty())w[i]=min(w[i],read());
124     dfs1(1),dfs2(1),dfs(1,1);
125     for(int i=1;i<=q;i++){
126         x=(Read()^ans)%n+1,y=(Read()^ans)%n+1;
127         ans=calc(x,y),ans1^=ans,ans2+=ans;
128     }
129     printf("%d %lld\n",ans1,ans2);
130     return 0;
131 }
View Code

 

posted @ 2022-01-20 14:00  PYWBKTDA  阅读(71)  评论(0编辑  收藏  举报