2019.10.10口胡题

D1T1

维护儿子和孙子异或和,每次改x只改x的父亲和爷爷,复杂度度O(n),以后口胡题尽量还是不要写正解+暴力+数据生成+对拍了,到最后题都没时间看完

 1 #include<iostream>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #define int long long
 8 using namespace std;
 9 const int N=1e6+10,mod=1e9+7;
10 int sum,tot,n,m,s[N],g[N],a[N],f[N],head[N],to[N*2],ne[N*2]; //s:2 g:1
11 inline int read()
12 {
13         register int sum,k=1;register char s;
14         while(s=getchar(),s<'0'||s>'9') if(s=='-') k=-1;sum=s-'0';
15         while(s=getchar(),s>='0'&&s<='9') sum=sum*10+s-'0';
16         return k*sum;
17 }
18 void add(int x,int y)
19 {
20         to[++tot]=y;
21         ne[tot]=head[x];
22         head[x]=tot;
23 }
24 void dfs(int x,int fa)
25 {
26         f[x]=fa;
27         for(int i=head[x];i;i=ne[i])
28         {
29                 int y=to[i];
30                 if(y==fa) continue;
31                 g[x]^=a[y];
32                 if(fa) s[fa]^=a[y];
33                 dfs(y,x);
34         }
35 }
36 signed main()
37 {
38         freopen("1.in","r",stdin);
39         freopen("1.out","w",stdout);
40         n=read(),m=read();
41         for(int i=1;i<=n;i++) a[i]=read();
42         for(int i=1,x,y;i<n;i++)
43         {
44                 x=read(),y=read();
45                 add(x,y),add(y,x);
46         }
47         dfs(1,0);
48         for(int i=1,x,y,cnt;i<=m;i++)
49         {
50                 x=read(),y=read();
51                 if(f[x]) g[f[x]]^=a[x]^y;
52                 if(f[f[x]]) s[f[f[x]]]^=a[x]^y;
53                 a[x]=y;
54                 cnt=a[x]^s[x]^g[x]^a[f[x]]^a[f[f[x]]];
55                 if(f[x]) cnt^=g[f[x]]^a[x];
56                 sum=(sum+(i*i%mod)*cnt%mod)%mod;
57         }
58         printf("%lld",sum);
59         return 0;
60 }
T1

 D1T2

听LNC口胡效果不错

 D1T3

咕咕

D2T1

考虑树的部分分,我们发现一定是所以负边权之和,因为叶子节点只有一个度,根据流量守恒,流量一定为零,推得所有边都为零,贪心地把所有负边权观察了就好。

对于环也一样,搞一发最小生成森林即可

D2T2T3

详见题解

原文地址:https://www.cnblogs.com/AthosD/p/11650655.html