好久没写树分治了,稍微复习一下,顺便吐一吐槽。。。
最近一场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;
}