CF869D The Overdosing Ubiquity Problem solving report:
meaning of the title
Given a complete binary tree with \ (n \) nodes, the father of point \ (K \) is \ (\ lfloor\frac{k}{2}\rfloor \), add \ (m \) edges to find the number of simple paths with different essence.
\(1\leqslant n\leqslant 10^9,0\leqslant m\leqslant 4\).
analysis
Give a big constant and large code size, but it's a good idea.
First, the number of paths that do not pass through the new edge is \ (O(n^2) \), and then consider the number of schemes that force them to pass through the new edge.
Because \ (m \) is very small, we can enumerate which edges are selected, the order of edges, the direction of edges (that is, undirected edges become directed edges), and then consider the number of paths passing through the specified edges in order.
Let \ ((x_i,y_i) \) add A new edge (A total of \ (k \) to the selected \ (I \), and take out two paths \ (A \) and \ (B \).
\(A \): walk from \ (y_1 \) along the edge of the tree to \ (x_2 \), then walk \ ((x_2,y_2) \), and then walk from \ (y_2 \) along the edge of the tree to \ (x_3 \)
\(B \): \ (x_1 \) the path from the edge of the tree to \ (y_k \).
If \ (A \) intersects with \ (B \), it can be found that the starting point of the path passing through these designated edges must be the point that \ (x \) can reach along the edge of the tree without passing through the inner point of \ (A \), and the end point must be the point that \ (y \) can reach along the edge of the tree without passing through the inner point of \ (B \).
This thing can be found directly in the tree. It can also be found that this connected block must be the result of removing several subtrees from A subtree. Both the large subtree and the removed subtree can be calculated by enumerating the points on \ (A \). See the code for details. (\ (\ text{dfs} \) section)
If \ (A \) and \ (B \) do not intersect, it can be found that we can almost choose two points as the starting point and ending point among the points reached by \ (A \) and \ (B \), but these two points \ (s,t \) must meet the requirement that \ ((x_1,s) \) and \ ((y_k,t) \) do not intersect
, we enumerate all the points on \ (B \) so that the enumerated points are the ancestors of \ (s \), then \ (t \) must be in the subtree of the point further behind \ (B \), so the prefix and sum are finished.
Then you write a lot of code, and then you just need enough patience to debug!
Time complexity \ (o) (m \ log n) ^ 3M! 4 ^ m) \), very loose, casual.
code
#include<stdio.h> #include<algorithm> #include<string.h> #include<map> using namespace std; const int maxn=1000005,mod=1000000007; int n,m,ans; int x[maxn],y[maxn],t[maxn],p[maxn],q[maxn],aa[maxn],bb[maxn],cc[maxn],dd[maxn],no[maxn]; map<int,int>vis; int getsize(int x){ // printf("getsize(%d)=",x); int r=x,dep=1; while((r<<1|1)<=n) r=(r<<1|1),dep++; int out=(r<<1|1); // printf("%d\n",((1<<dep)-1)+max((1<<dep)-(out-n),0)); return ((1<<dep)-1)+max((1<<dep)-(out-n),0); } int isfa(int x,int y){ while(y){ if(x==y) return 1; y>>=1; } return 0; } void dfs(int x,int ban1,int ban2,int &c){ int nos=0; for(map<int,int>::iterator it=vis.begin();it!=vis.end();it++) if(it->second&&it->first!=x) no[++nos]=it->first; if(ban1&&vis[ban1]==0&&ban1!=x) no[++nos]=ban1; if(ban2&&vis[ban2]==0&&ban2!=x) no[++nos]=ban2; sort(no+1,no+1+nos); // for(int i=1;i<=nos;i++) // printf("%d%c",no[i],i==nos? '\n':' '); int fa=0; for(int i=1;i<=nos;i++) if(no[i]&&no[i]<x&&isfa(no[i],x)) fa=max(fa,no[i]); int y=x,lst=0; while(y!=fa) lst=(y&1),y>>=1; fa=(fa<<1)|lst,c=getsize(fa); for(int i=1;i<=nos;i++) if(no[i]>fa&&isfa(fa,no[i])) for(int j=i+1;j<=nos;j++) if(no[j]&&no[j]>fa&&isfa(no[i],no[j])) no[j]=0; for(int i=1;i<=nos;i++) if(no[i]&&fa<no[i]&&isfa(fa,no[i])){ // printf("i=%d no[i]=%d %d\n",i,no[i],getsize(no[i])); c-=getsize(no[i]); } // printf("y=%d fa=%d\n",y,fa); // printf("(dfs %d %d %d)=%d(fa=%d)\n",x,ban1,ban2,c,fa); /*if(x==ban||x>n||x<1) return ; vis[x]=1,c++; if(vis[x>>1]==0) dfs(x>>1,ban,c); if(vis[x<<1]==0) dfs(x<<1,ban,c); if(vis[x<<1|1]==0) dfs(x<<1|1,ban,c); */ } int main(){ scanf("%d%d",&n,&m),ans=1ll*n*n%mod; if(m==0){ printf("%d\n",ans); return 0; } for(int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]); for(int i=1;i<(1<<m);i++){ int tot=0; for(int j=1;j<=m;j++) if((i>>(j-1))&1) t[++tot]=j,p[tot]=tot; do{ for(int j=1;j<=tot;j++) q[j]=t[p[j]]; for(int j=0;j<(1<<tot);j++){ // printf("i=%d j=%d ans=%d\n",i,j,ans); vis.clear(); for(int k=1;k<=tot;k++) vis[x[q[k]]]=vis[y[q[k]]]=1; for(int k=1;k<=tot;k++) if((j>>(k-1))&1) swap(x[q[k]],y[q[k]]); int flg=0; for(int k=1;k<=tot;k++) for(int r=k+1;r<=tot;r++) if(x[q[k]]==x[q[r]]||y[q[k]]==y[q[r]]||x[q[k]]==y[q[r]]||(y[q[k]]==x[q[r]]&&r!=k+1)) flg=1; for(int k=1;k<tot;k++){ int X=y[q[k]],Y=x[q[k+1]],a=__builtin_clz(X),b=__builtin_clz(Y),s=X,t=Y; while(a<b){ s>>=1,a++; if(s!=t) flg|=vis[s],vis[s]=1; } while(b<a){ t>>=1,b++; if(s!=t) flg|=vis[t],vis[t]=1; } while(s!=t){ s>>=1,a++,flg|=vis[s],vis[s]=1; t>>=1,b++; if(s!=t) flg|=vis[t],vis[t]=1; } } // for(int k=1;k<=tot;k++) // printf("xx=%d yy=%d\n",x[k],y[k]); if(flg==0){ int X=x[q[1]],Y=y[q[tot]],a=__builtin_clz(X),b=__builtin_clz(Y),s=X,t=Y,f=0,as=0,bs=0,cs=0; while(a<b){ s>>=1,a++; if(s!=t) f|=vis[s],aa[++as]=s; } while(b<a){ t>>=1,b++; if(s!=t) f|=vis[t],bb[++bs]=t; } while(s!=t){ s>>=1,a++,f|=vis[s],aa[++as]=s; t>>=1,b++; if(s!=t) f|=vis[t],bb[++bs]=t; } if(f){ // puts("case1"); int c0=0,c1=0; dfs(X,0,0,c0),dfs(Y,0,0,c1); ans=(ans+1ll*c0*c1)%mod; } else{ // puts("case2"); for(int k=1;k<=as;k++) cc[++cs]=aa[k]; for(int k=bs;k>=1;k--) cc[++cs]=bb[k]; // printf("X=%d Y=%d\n",X,Y); cc[0]=X,cc[cs+1]=Y; /* puts("CC"); for(int k=0;k<=cs+1;k++) printf("%d%c",cc[k],k==cs+1? '\n':' ');*/ int all=0; // puts("A"); dd[0]=0,dfs(X,0,cc[1],dd[0]),all+=dd[0]; for(int k=1;k<=cs;k++) dd[k]=0,dfs(cc[k],cc[k-1],cc[k+1],dd[k]),all+=dd[k]; // puts("B"); dd[cs+1]=0,dfs(Y,0,cc[cs],dd[cs+1]),all+=dd[cs+1]; /* for(int k=0;k<=cs+1;k++) printf("k=%d dd[k]=%d\n",k,dd[k]);*/ for(int k=0;k<=cs;k++) all-=dd[k],ans=(ans+1ll*dd[k]*all)%mod; } } // printf("i=%d j=%d ans=%d\n",i,j,ans); for(int k=1;k<=tot;k++) if((j>>(k-1))&1) swap(x[q[k]],y[q[k]]); } }while(next_permutation(p+1,p+1+tot)); // printf("i=%d ans=%d\n",i,ans); } printf("%d\n",ans); return 0; }