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
",(((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 }
原文地址:https://www.cnblogs.com/--HPY-7m/p/13418712.html