HDU多校2020 第二场 --Count on a Tree II Striking Back(概率神仙题
题意:http://acm.hdu.edu.cn/showproblem.php?pid=6765
给你一颗树,树上每个点都有颜色,问你a-b链上的颜色种数和c-d链上的颜色种数哪个大
思路:
首先如果链上颜色越多那么可能的答案就越小,【0,1】区间选k个数的最小值的期望是1/(k+1),我们就把每个颜色随机一个对应值,两条链取min后的值比下大小就行了(可以尝试多取几次样本)
标程
1 #include<cstdio> 2 #include<algorithm> 3 #include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; 4 using namespace std; 5 typedef unsigned int U; 6 typedef long long ll; 7 const int N=500010,K=30; 8 const U inf=~0U; 9 int Case,n,m,i,j,last,op,x,y,A,B,C,D,col[N],g[N],v[N<<1],nxt[N<<1],ed; 10 int f[N],d[N],size[N],son[N],top[N],loc[N],q[N],dfn; 11 U w[N][K],val[1111111][K],tmp[K]; 12 U SX=335634763,SY=873658265,SZ=192849106,SW=746126501; 13 inline U xorshift128(){ 14 U t=SX^(SX<<11); 15 SX=SY; 16 SY=SZ; 17 SZ=SW; 18 return SW=SW^(SW>>19)^t^(t>>8); 19 } 20 inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} 21 void dfs1(int x,int y){ 22 f[x]=y,d[x]=d[y]+1,size[x]=1; 23 for(int i=g[x];i;i=nxt[i]){ 24 int u=v[i]; 25 if(u==y)continue; 26 dfs1(u,x); 27 size[x]+=size[u]; 28 if(size[u]>size[son[x]])son[x]=u; 29 } 30 } 31 void dfs2(int x,int y){ 32 q[loc[x]=++dfn]=x; 33 top[x]=y; 34 if(son[x])dfs2(son[x],y); 35 for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]&&v[i]!=son[x])dfs2(v[i],v[i]); 36 } 37 inline void up(int x){for(int i=0;i<K;i++)val[x][i]=min(val[x<<1][i],val[x<<1|1][i]);} 38 void build(int x,int a,int b){ 39 if(a==b){ 40 int o=col[q[a]]; 41 for(int i=0;i<K;i++)val[x][i]=w[o][i]; 42 return; 43 } 44 int mid=(a+b)>>1; 45 build(x<<1,a,mid),build(x<<1|1,mid+1,b); 46 up(x); 47 } 48 void change(int x,int a,int b,int c,int p){ 49 if(a==b){ 50 for(int i=0;i<K;i++)val[x][i]=w[p][i]; 51 return; 52 } 53 int mid=(a+b)>>1; 54 if(c<=mid)change(x<<1,a,mid,c,p);else change(x<<1|1,mid+1,b,c,p); 55 up(x); 56 } 57 inline void umin(U&a,U b){a>b?(a=b):0;} 58 void ask(int x,int a,int b,int c,int d){ 59 if(c<=a&&b<=d){ 60 for(int i=0;i<K;i++)umin(tmp[i],val[x][i]); 61 return; 62 } 63 int mid=(a+b)>>1; 64 if(c<=mid)ask(x<<1,a,mid,c,d); 65 if(d>mid)ask(x<<1|1,mid+1,b,c,d); 66 } 67 inline ll estimate(int x,int y){ 68 for(int i=0;i<K;i++)tmp[i]=inf; 69 for(;top[x]!=top[y];x=f[top[x]]){ 70 if(d[top[x]]<d[top[y]])swap(x,y); 71 ask(1,1,n,loc[top[x]],loc[x]); 72 } 73 if(d[x]<d[y])swap(x,y); 74 ask(1,1,n,loc[y],loc[x]); 75 ll ret=0; 76 for(int i=0;i<K;i++)ret+=tmp[i]; 77 return ret; 78 } 79 int main(){ 80 srand(((unsigned)time(NULL))); 81 for(i=1;i<N;i++)for(j=0;j<K;j++)w[i][j]=rand()%1000000000+1; 82 scanf("%d",&Case); 83 while(Case--){ 84 scanf("%d%d",&n,&m); 85 for(ed=dfn=last=i=0;i<=n;i++)g[i]=f[i]=d[i]=size[i]=son[i]=0; 86 for(i=1;i<=n;i++)scanf("%d",&col[i]); 87 for(i=1;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x); 88 dfs1(1,0); 89 dfs2(1,1); 90 build(1,1,n); 91 while(m--){ 92 scanf("%d%d%d",&op,&A,&B); 93 A^=last,B^=last; 94 if(op==1)change(1,1,n,loc[A],B); 95 else{ 96 scanf("%d%d",&C,&D); 97 C^=last,D^=last; 98 ll E=estimate(A,B),F=estimate(C,D); 99 //printf(">> %.15f %.15f\n",(((double)(1ULL<<32))*K)/E-1,(((double)(1ULL<<32))*K)/F-1); 100 if(E<F){ 101 puts("Yes"); 102 last++; 103 }else puts("No"); 104 } 105 } 106 } 107 }