• [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
  • 相关阅读:
    远程获取图片尺寸
    python httplib get和post获取数据
    python 之 logging
    php artisan常用方法
    html页面制作css基本设置
    zlib-1.2.7/libpng-1.5.9 instead of zlib-1.2.8/libpng-1.6.6
    shell脚本自动拉起启动程序
    php截取中文无乱码
    路飞学城1之课程与课程详细
    vuex(数据商店实现思想)day06
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15826117.html
Copyright © 2020-2023  润新知