这题主要学习两点,一个是LCA具有可加性,这个在做题的时候考虑到了;
另一个是对于在一个具备可加性的点集中去除一个点再看剩下点的影响,可以考虑预处理出前缀和以及后缀和,然后枚举删掉的节点进行计算。rainy说这是非常常见的套路。
1 #include "bits/stdc++.h" 2 using namespace std; 3 const int MAX=2e5+5; 4 int n,m,w[MAX]; 5 int weia[MAX],weib[MAX]; 6 int lcal[MAX],lcar[MAX],lcbl[MAX],lcbr[MAX]; 7 int tot,head[MAX],adj[MAX<<1],nxt[MAX<<1]; 8 int fa[MAX][21],deep[MAX]; 9 inline int read(){ 10 int an=0,x=1;char c=getchar(); 11 while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();} 12 while (c>='0' && c<='9') {an=(an<<3)+(an<<1)+c-'0';c=getchar();} 13 return an*x; 14 } 15 void addedge(int u,int v){ 16 tot++;adj[tot]=v,nxt[tot]=head[u],head[u]=tot; 17 } 18 void dfs(int x,int ff){ 19 int i,j; 20 for (i=1;i<=20;i++){ 21 if (deep[x]<(1<<i)) break; 22 fa[x][i]=fa[ fa[x][i-1] ][i-1]; 23 } 24 for (i=head[x];i;i=nxt[i]){ 25 if (adj[i]==ff) continue; 26 fa[adj[i]][0]=x;deep[adj[i]]=deep[x]+1; 27 dfs(adj[i],x); 28 } 29 } 30 int lca(int x,int y){ 31 if (deep[x]<deep[y]) swap(x,y); 32 int i,j,dd=deep[x]-deep[y]; 33 for (i=20;i>=0;i--) 34 if (dd&(1<<i)) 35 x=fa[x][i]; 36 for (i=20;i>=0;i--) 37 if (fa[x][i]!=fa[y][i]) 38 x=fa[x][i],y=fa[y][i]; 39 return x==y?x:fa[x][0]; 40 } 41 int main(){ 42 freopen ("a.in","r",stdin); 43 freopen ("a.out","w",stdout); 44 int i,j,u,v; 45 scanf("%d%d",&n,&m); 46 for (i=1;i<=m;i++) scanf("%d",w+i); 47 for (i=1;i<=n;i++) scanf("%d",weia+i); 48 for (i=1;i<n;i++){ 49 scanf("%d",&v); 50 addedge(v,i+1); 51 addedge(i+1,v); 52 } 53 for (i=1;i<=n;i++) scanf("%d",weib+i); 54 for (i=1;i<n;i++){ 55 scanf("%d",&v); 56 addedge(v+n,i+1+n); 57 addedge(i+1+n,v+n); 58 } 59 dfs(1,0); 60 dfs(n+1,0); 61 lcal[1]=w[1];lcar[m]=w[m]; 62 lcbl[1]=w[1]+n;lcbr[m]=w[m]+n; 63 for (i=2;i<=m;i++){ 64 lcal[i]=lca(lcal[i-1],w[i]); 65 lcbl[i]=lca(lcbl[i-1],w[i]+n); 66 // cout<<w[i]<<' '<<lcal[i]<<' '<<lcbl[i]-n<<endl; 67 } 68 // cout<<endl; 69 for (i=m-1;i>=1;i--){ 70 lcar[i]=lca(lcar[i+1],w[i]); 71 lcbr[i]=lca(lcbr[i+1],w[i]+n); 72 // cout<<w[i]<<' '<<lcar[i]<<' '<<lcbr[i]-n<<endl; 73 } 74 int ans=0; 75 if (weia[lcar[2]]>weib[lcbr[2]-n]) ans++; 76 if (weia[lcal[m-1]]>weib[lcbl[m-1]-n]) ans++; 77 for (i=2;i<m;i++){ 78 int xx=lca(lcal[i-1],lcar[i+1]); 79 int yy=lca(lcbl[i-1],lcbr[i+1]); 80 if (weia[xx]>weib[yy-n]) 81 ans++; 82 } 83 printf("%d",ans); 84 return 0; 85 }