【2019ICPC西安邀请赛】J.And And And(点分治)

时间:2019-10-15
本文章向大家介绍【2019ICPC西安邀请赛】J.And And And(点分治),主要包括【2019ICPC西安邀请赛】J.And And And(点分治)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题意:给定一棵n个点带边权的树,定义每条路径的值为路径上边权的异或和

如果一条路径的值为0,其对答案的贡献为所有包含这条路径的路径条数

求答案膜1e9+7

n<=1e5,0<=边权<=1e18

思路:参考https://dudulu.net/blog/?p=1654

考场上还剩2小时的时候开的这题,乍一看觉得很可做就是个裸的点分,结果发现自己不会算贡献,场上连样例都没调出来

现在也是写了两天发现不会算贡献,参考了dalao的博客才会

每条路径的权值可以用两个端点分别能扩展的点的个数的乘积来算

预处理一下以1为根每个点的父亲和子树大小

在分治过程中,假设有u->……->pre->v这条路径

对于v这个点:

如果pre=f[v]可扩展的个数就是siz[v]

若果pre!=f[v]可扩展的个数就是n-siz[pre]

对于分治中心u和u的每个直接分支v:

如果u=f[v]可扩展的个数就是n-siz[v]

如果u!=f[v]可扩展的个数就是siz[u]

扔到map里记一下前缀和

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 //typedef pair<ll,ll>P;
 11 #define N  200010
 12 #define M  200010
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pb push_back
 17 #define pi acos(-1)
 18 #define mem(a,b) memset(a,b,sizeof(a))
 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 21 #define lowbit(x) x&(-x)
 22 #define Rand (rand()*(1<<16)+rand())
 23 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 24 #define ls p<<1
 25 #define rs p<<1|1
 26 
 27 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 28       double eps=1e-6;
 29       ll INF=1e15;
 30       int dx[4]={-1,1,0,0};
 31       int dy[4]={0,0,-1,1};
 32 
 33 struct node
 34 {
 35     int x;
 36     ll y;
 37 }q[N];
 38 
 39 map<ll,ll>mp1,mp2;
 40 map<ll,ll>::iterator it;
 41 int head[N],vet[N],nxt[N],c[N],flag[N],son[N],
 42     s[N],siz[N],f[N],pre[N],tot,root,sum,n,now;
 43 ll len[N],dis[N],ans;
 44 
 45 int read()
 46 {
 47    int v=0,f=1;
 48    char c=getchar();
 49    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 50    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 51    return v*f;
 52 }
 53 
 54 void add(int a,int b,ll c)
 55 {
 56     nxt[++tot]=head[a];
 57     vet[tot]=b;
 58     len[tot]=c;
 59     head[a]=tot;
 60 }
 61 
 62 void getroot(int u,int fa)
 63 {
 64     son[u]=1; c[u]=0;
 65     int e=head[u];
 66     while(e)
 67     {
 68         int v=vet[e];
 69         if(v!=fa&&!flag[v])
 70         {
 71             getroot(v,u);
 72             son[u]+=son[v];
 73             c[u]=max(c[u],son[v]);
 74         }
 75         e=nxt[e];
 76     }
 77     c[u]=max(c[u],sum-c[u]);
 78     if(c[u]<c[root]) root=u;
 79 }
 80 
 81 void dfs(int u,int fa)
 82 {
 83     siz[u]=1;
 84     int e=head[u];
 85     while(e)
 86     {
 87         int v=vet[e];
 88         if(v!=fa)
 89         {
 90             f[v]=u;
 91             dfs(v,u);
 92             siz[u]+=siz[v];
 93         }
 94         e=nxt[e];
 95     }
 96 }
 97 
 98 void getdis(int u,int fa)
 99 {
100     if(fa==f[u])
101     {
102         mp1[dis[u]]=(mp1[dis[u]]+siz[u])%MOD;
103         if(dis[u]==0) ans=(ans+1ll*siz[u]*now%MOD)%MOD;
104     }
105      else
106      {
107          mp1[dis[u]]=(mp1[dis[u]]+n-siz[fa])%MOD;
108          if(dis[u]==0) ans=(ans+1ll*(n-siz[fa])*now%MOD)%MOD;
109      }
110     int e=head[u];
111     while(e)
112     {
113         int v=vet[e];
114         if(v!=fa&&!flag[v])
115         {
116             dis[v]=dis[u]^len[e];
117             getdis(v,u);
118         }
119         e=nxt[e];
120     }
121 }
122 
123 void calc(int u)
124 {
125     dis[u]=0;
126     int e=head[u];
127     while(e)
128     {
129         int v=vet[e];
130         if(flag[v])
131         {
132             e=nxt[e];
133             continue;
134         }
135         mp1.clear();
136         if(f[v]==u) now=n-siz[v];
137          else now=siz[u];
138         dis[v]=len[e];
139         getdis(v,u);
140         it=mp1.begin();
141         while(it!=mp1.end())
142         {
143             ll w=it->fi,t=it->se;
144             ans=(ans+t*mp2[w]%MOD)%MOD;
145             it++;
146         } 
147         it=mp1.begin();
148         while(it!=mp1.end())
149         {
150             ll w=it->fi,t=it->se;
151             mp2[w]=(mp2[w]+t)%MOD;
152             it++;
153         }
154         e=nxt[e];
155     }
156     mp2.clear();
157 }
158 
159 void solve(int u)
160 {
161     flag[u]=1;
162     calc(u);
163     int e=head[u];
164     while(e)
165     {
166         int v=vet[e];
167         if(!flag[v])
168         {
169             sum=son[v]; root=0;
170             getroot(v,0);
171             solve(root);
172         }
173         e=nxt[e];
174     }
175 }
176 
177 int main()
178 {
179     //freopen("1.in","r",stdin);
180     //freopen("1.out","w",stdout);
181     n=read();
182     rep(i,1,n) head[i]=flag[i]=0;
183     tot=0;
184     rep(i,2,n)
185     {
186         int x=read();
187         ll y;
188         scanf("%lld",&y);
189         add(i,x,y);
190         add(x,i,y);
191     }
192     dfs(1,0);
193     sum=n; c[0]=n; ans=0; root=0;
194     getroot(1,0);
195     solve(root);
196     printf("%lld\n",ans);
197     return 0;
198 }

原文地址:https://www.cnblogs.com/myx12345/p/11678248.html