好久没写树分治了,稍微复习一下,顺便吐一吐槽。。。
最近一场warming两场网络赛,前两次还好,最后一次真是跌出历史最低水平了,整个队伍处于一种奇怪的状态,然后最近又在牙疼,貌似是长智齿,各种混乱。。。
这道题是询问树上有多少条路径的点权积是三次方数,直接点分治求过每个点的方案,每次用map暴力统计一下,一开始re是一直用dfs写树分治爆栈了,以后能bfs还是尽量bfs吧。。。后来tle,是我脑残用string存在map里面,明明是可以压位的,string的唯一好处是好输出调试。。。后来wa是win8用lld读入longlong,结果我定义的int,用I64d不报错,真心坑。。。
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <map> #include <vector> #include <utility> const int oo=1073741819; using namespace std; int tail[200000],next[2000000],sora[2000000]; int a[60000][31],st[60000],v[60000],size[60000],rt[60000],rel[60000],bj[60000]; int pri[60000][31],ans; long long d[36],b[60000],p[31],w[60000]; int ts[60000]; int c[31],sign; map < long long , int > hash; int n,ss,rr,w_time,k,max_size,root; void bfs(int s) { int h,r,ne,na; h=r=0; st[r=1]=s,v[s]=w_time; for (;h<r;) { ne=st[++h],size[ne]=0; for (int i=ne;next[i];) { i=next[i],na=sora[i]; if (!rel[na] && v[na]!=w_time) { v[na]=w_time,rt[na]=ne; st[++r]=na; } } } for (int i=r;i>=1;i--) { ne=st[i]; size[ne]++; //cout<<ne<<' '<<size[ne]<<endl; size[rt[ne]]+=size[ne]; int tmp=r-size[ne]; for (int i=ne;next[i];) { i=next[i],na=sora[i]; if (v[na]==w_time && na!=rt[ne]) tmp=max(tmp,size[na]); } if (tmp<max_size) max_size=tmp,root=ne; //cout<<ne<<' '<<tmp<<endl; } } void bfs2(int s) { int h,r,ne,na; h=r=0; st[r=1]=s,v[s]=w_time,bj[s]=sign; for (;h<r;) { ne=st[++h],ts[++rr]=ne; hash[b[ne]]++; for (int i=ne;next[i];) { i=next[i],na=sora[i]; if (!rel[na] && v[na]!=w_time) { v[na]=w_time,bj[na]=sign; st[++r]=na; b[na]=0; for (int i=1;i<=k;i++) a[na][i]=(a[ne][i]+pri[na][i])%3,b[na]=b[na]+d[i]*a[na][i]; } } } } long long doit(int c[31],int e[31]) { long long tmp=0; tmp=0; for (int i=1;i<=k;i++) tmp=tmp+d[i]*(((3-c[i]+e[i])%3)); return tmp; } void mysoul(int s) { // cout<<' '<<s<<endl; max_size=oo,root=0; w_time++; bfs(s); s=root,rel[s]=1; // cout<<max_size<<endl; for (int i=1;i<=k;i++) a[s][i]=pri[s][i]%3; rr=0,hash.clear(); for (int i=s,ne;next[i];) { i=next[i],ne=sora[i]; if (!rel[ne]) { ++w_time,sign=ne; b[ne]=0; for (int i=1;i<=k;i++) a[ne][i]=(a[s][i]+pri[ne][i])%3,b[ne]+=d[i]*a[ne][i]; //cout<<1<<endl; bfs2(ne); } } //cout<<' '<<s<<endl; long long tmp=doit(a[s],a[s]); ans+=hash[tmp]*2; // cout<<tmp<<' '<<ans<<' '<<bj[5]<<' '<<bj[4]<<endl; //for (int i=1;i<=rr;i++) cout<<b[ts[i]]<<' ';cout<<endl; for (int i=1,op,ed;i<=rr;i=ed+1) { op=i; //cout<<hash[6]<<endl; for (ed=op;bj[ts[ed]]==bj[ts[op]] && ed<=rr;ed++) hash[b[ts[ed]]]--; ed--; // cout<<op<<' '<<ed<<endl; for (int j=op;j<=ed;j++) { tmp=doit(a[ts[j]],a[s]); ans+=hash[tmp]; // cout<<ts[j]<<' '<<tmp<<' '<<b[ts[j]]<<' '<<ans<<endl; } for (int j=op;j<=ed;j++) hash[b[ts[j]]]++; } // cout<<s<<' '<<ans<<endl; for (int i=s,ne;next[i];) { i=next[i],ne=sora[i]; if (!rel[ne]) mysoul(ne); } } void origin() { ss=n; for (int i=1;i<=n;i++) tail[i]=i,next[i]=0; } void link(int x,int y) { ++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0; ++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x,next[ss]=0; } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); for (;cin>>n;) { scanf("%d",&k); origin(); for (int i=1;i<=k;i++) scanf("%lld",&p[i]); d[0]=1; for (int i=1;i<=k;i++) d[i]=d[i-1]*3; for (int i=1;i<=n;i++) scanf("%lld",&w[i]); for (int i=1;i<=n;i++) { long long tmp=w[i]; for (int j=1;j<=k;j++) { pri[i][j]=0; for (;tmp && tmp%p[j]==0;tmp/=p[j]) pri[i][j]++; } } for (int i=1;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); link(x,y); } for (int i=1;i<=n;i++) rel[i]=0; for (int i=1;i<=n;i++) v[i]=0; w_time=0; ans=0; mysoul(1); for (int i=1;i<=n;i++) { int tmp=0; for (int j=1;j<=k;j++) tmp+=pri[i][j]%3; ans+=(tmp==0)*2; } cout<<ans/2<<endl; } return 0; }