十七波 Q Falsita、P[Ynoi2017]由乃的OJ
description:
她们所在的精神世界是一棵以 1 号节点为根的树,每个树上的节点 u 都有一个权值Wu,她们每个人分别都在一个节点上,达成共识的方法就是两个人都到达一个共识节点(即到达它们的最近公共祖先)。
一个点 u 与另外一个点 v 之间想要达到共识需要花费的代价为Wu+Wv。
有时两人的精神有所触动时,有时点的权值会改变成某个数,有时以某个点的子树中的所有点的权值会加上某个数。
Falsita 和 Fine 经常需要达成共识,每一次询问,已知达成的共识节点,求她们花费的期望代价。
- S u delta 表示将节点 u 的权值加上 delta 。
- M u delta 表示将以节点 u 为根的子树中的所有节点的权值加上 delta。
- Q u 表示询问共识节点为 u 时的答案。
solution:
求值
我们将修改分为两种情况,考虑把修改产生的影响分为向上,和向下的
- 对于一个节点的修改,会对根节点,到这个点的路径上的点都产生贡献;
- 如果只改变节点本身,对下面的子树不会有影响,
code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e5+10;
ll n,m,w[N];
ll en[N],nex[N],lst[N],tot;
void add(ll x,ll y){en[++tot]=y;nex[tot]=lst[x];lst[x]=tot;}
ll dep[N],f[N],sz[N],sum[N];
ll chu[N],zi[N];
ll top[N],son[N],bl[N],nid[N],id,ou[N];
void dfs(ll u,ll fa){
sum[u] = w[u];sz[u] = 1;
f[u] = fa;ll Msz = 0;
for(ll i=lst[u];i;i=nex[i])
{
ll v = en[i];
if(v==fa)continue;
dep[v] = dep[u]+1;dfs(v,u);
sz[u]+=sz[v];chu[u]-=sz[v]*sz[v];
sum[u]+=sum[v];zi[u]-=sz[v]*sum[v];
if(sz[v]>Msz){
son[u] = v;
Msz = sz[v];
}
}
chu[u]+=sz[u]*sz[u]-1;
zi[u]+=sz[u]*sum[u]-w[u];
}
void ddfs(ll u,ll anc){
nid[u] = ++id;bl[id] = u;top[u] = anc;
if(son[u])ddfs(son[u],anc);
for(ll i=lst[u];i;i=nex[i])
{
ll v = en[i];
if(v==f[u]||v == son[u])continue;
ddfs(v,v);
}
ou[u]=id;
}
ll lzy1[N<<3],lzy2[N<<3],seg[N<<3];
void build(ll p,ll l,ll r){
if(l==r)
{
seg[p] = zi[bl[l]];
// printf("%lld %lld\n",l,seg[p]);
return;
}
ll mid = (l + r) >> 1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void pushdown(ll p){
lzy1[p<<1]+=lzy1[p];lzy1[p<<1|1]+=lzy1[p];
lzy2[p<<1]+=lzy2[p];lzy2[p<<1|1]+=lzy2[p];
lzy2[p]=lzy1[p] = 0;
}
//´øson
void modify1(ll p,ll l,ll r,ll x,ll y,ll z){
if(x>y)return;
if(l>=x&&r<=y)
{
lzy1[p]+=z;return;
}
if(l==r)return;
if(lzy1[p])pushdown(p);
ll mid = (l + r) >> 1;
if(x<=mid)modify1(p<<1,l,mid,x,y,z);
if(y>mid)modify1(p<<1|1,mid+1,r,x,y,z);
return;
}
//ÐÞ¸Ä×ÓÊ÷
void modify3(ll p,ll l,ll r,ll x,ll y,ll z){
if(x>y)return;
if(l>=x&&r<=y)
{
lzy2[p]+=z;return;
}
if(l==r)return;
if(lzy2[p])pushdown(p);
ll mid = (l + r) >> 1;
if(x<=mid)modify3(p<<1,l,mid,x,y,z);
if(y>mid)modify3(p<<1|1,mid+1,r,x,y,z);
return;
}
//ÐÞ¸ÄÖØÁ´Á´½Ó´¦(µ¥µãÐ޸ģ©
void modify2(ll p,ll l,ll r,ll x,ll v,ll z){
if(l==r)
{
seg[p]+=z*(sz[bl[x]]-sz[v]);return;
}
ll mid = (l + r) >> 1;
if(x<=mid)modify2(p<<1,l,mid,x,v,z);
else modify2(p<<1|1,mid+1,r,x,v,z);
}
double query(ll p,ll l,ll r,ll x){
if(l==r)
{
ll tmp = bl[x];
// printf("%lld %lld\n",seg[p],lzy1[p]);
return 2.00*(lzy1[p]*(sz[tmp]-sz[son[tmp]])+seg[p])/(1.00*chu[bl[l]])+2.00*lzy2[p];
}
if(lzy1[p]||lzy2[p])pushdown(p);
ll mid = (l + r) >> 1;
if(x<=mid)return query(p<<1,l,mid,x);
else return query(p<<1|1,mid+1,r,x);
}
void change(ll u,ll x){
while(top[u]!=top[1])
{
modify1(1,1,n,nid[top[u]],nid[u]-1,x);
modify2(1,1,n,nid[f[top[u]]],top[u],x);
u = f[top[u]];
}
modify1(1,1,n,nid[1],nid[u]-1,x);
}
int main(){
scanf("%lld%lld",&n,&m);
for(ll i=2,x;i<=n;i++){scanf("%lld",&x);add(x,i);}
for(ll i=1;i<=n;i++)scanf("%lld",w+i);
dfs(1,0);ddfs(1,1);
build(1,1,n);
sz[n+1]=1;
for(ll i=1,u,v;i<=m;i++)
{
char otp[2];
scanf("%s",otp);
if(otp[0]=='S')
{
scanf("%lld%lld",&u,&v);
change(u,v);modify2(1,1,n,nid[u],n+1,v);
}
if(otp[0]=='M')
{
scanf("%lld%lld",&u,&v);
change(u,sz[u]*v);
modify3(1,1,n,nid[u],ou[u],v);
}
if(otp[0]=='Q')
{
scanf("%lld",&u);
printf("%.6lf\n",query(1,1,n,nid[u]));
}
}
}
由乃的oj
**solution:**我们用wl[p][0/1];wr[p][0/1]来表示在p的区间内从左边/从右边全部以1/0输入最后得到的结果
update更新的时候我们就看根据(0/1)的情况保留需要的位数;
#include<bits/stdc++.h>
using namespace std;
const int N = 4e5+10;
const unsigned long long Top = 18446744073709551615ULL;
int n,m,K;
int en[N],nex[N],lst[N],tot;
void add(int x,int y){en[++tot]=y;nex[tot]=lst[x];lst[x]=tot;}
int f[N],dep[N],sz[N];
int son[N],top[N],nid[N],id;
void dfs(int u,int fa){
f[u] = fa;sz[u] = 1;int Msz = 0;
for(int i=lst[u];i;i=nex[i])
{
int v = en[i];
if(v==fa)continue;
dep[v] = dep[u] + 1;
dfs(v,u);
sz[u]+=sz[v];
if(sz[v]>Msz){
son[u] = v;Msz = sz[v];
}
}
return;
}
void ddfs(int u,int anc){
top[u] = anc;nid[u] = ++id;
if(son[u])ddfs(son[u],anc);
for(int i=lst[u];i;i=nex[i])
{
int v = en[i];
if(v==f[u]||v==son[u])continue;
ddfs(v,v);
}
}
unsigned long long wl[N<<3][2],wr[N<<3][2];
//L´Ó×óÈ룬R´ÓÓÒÈë
void update(int p){
unsigned long long el1,el0,er1,er0;
int ls = p<<1,rs = p<<1|1;
el1 = wl[ls][1];el0 = wl[ls][0];
er1 = wr[rs][1];er0 = wr[rs][0];
wl[p][1] = (wl[rs][1]&el1)+(wl[rs][0]&(~el1));
wl[p][0] = (wl[rs][1]&el0)+(wl[rs][0]&(~el0));
wr[p][1] = (wr[ls][1]&er1)+(wr[ls][0]&(~er1));
wr[p][0] = (wr[ls][1]&er0)+(wr[ls][0]&(~er0));
return;
}
void modify(int p,int l,int r,int x,unsigned long long w,int otp){
if(l==r)
{
if(otp==1)
{
wr[p][0] = wl[p][0] = 0;
wr[p][1] = wl[p][1] = w;
}
if(otp==2)
{
wr[p][0] = wl[p][0] = w;
wr[p][1] = wl[p][1] = Top;
}
if(otp==3)
{
wr[p][0] = wl[p][0] = w;
wr[p][1] = wl[p][1] = Top^w;
}
return;
}
int mid = (l + r) >> 1;
if(x<=mid)modify(p<<1,l,mid,x,w,otp);
else modify(p<<1|1,mid+1,r,x,w,otp);
update(p);
}
struct node{
unsigned long long num0,num1;
}ans2[1000];
node query(int p,int l,int r,int x,int y,int dir){
if(l>=x&&r<=y)
{
if(dir)return (node){wl[p][0],wl[p][1]};
else return (node){wr[p][0],wr[p][1]};
}
if(l == r)return(node){0,0};
int mid = (l + r) >> 1;
node tmp1,tmp2,tmp3;
if(x<=mid){
tmp1 = query(p<<1,l,mid,x,y,dir);
if(y<=mid)return tmp1;
}
if(y>mid){
tmp2 = query(p<<1|1,mid+1,r,x,y,dir);
if(x>mid)return tmp2;
}
if(dir)
{
tmp3.num0 = (tmp1.num0&tmp2.num1)+((~tmp1.num0)&tmp2.num0);
tmp3.num1 = (tmp1.num1&tmp2.num1)+((~tmp1.num1)&tmp2.num0);
}
else {
tmp3.num0 = (tmp2.num0&tmp1.num1)+((~tmp2.num0)&tmp1.num0);
tmp3.num1 = (tmp2.num1&tmp1.num1)+((~tmp2.num1)&tmp1.num0);
}
return tmp3;
}
unsigned long long gets(int u,int v,unsigned long long z){
int cnt2 = 0,flag = 0,l = 1,r = 0,mark1=0,mark0=0;
unsigned long long res1=0,res0=0,ans=0;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]){
ans2[++cnt2] = query(1,1,n,nid[top[v]],nid[v],l);
v =f[top[v]];
}
else {
node tmp = query(1,1,n,nid[top[u]],nid[u],r);
if(!mark1)res1 = tmp.num1,mark1=1;
else res1 = (res1&tmp.num1)+((~res1)&tmp.num0);
if(!mark0)res0 = tmp.num0,mark0=1;
else res0 = (res0&tmp.num1)+((~res0)&tmp.num0);
u = f[top[u]];
}
}
if(dep[u]>dep[v])ans2[++cnt2] = query(1,1,n,nid[v],nid[u],r);
else ans2[++cnt2] = query(1,1,n,nid[u],nid[v],l);
for(int i=cnt2;i>=1;i--)
{
if(!mark1)res1 = ans2[i].num1,mark1 = 1;
else res1 = (res1&ans2[i].num1)+((~res1)&ans2[i].num0);
if(!mark0)res0 = ans2[i].num0,mark0 = 1;
else res0 = (res0&ans2[i].num1)+((~res0)&ans2[i].num0);
}
for(int i=63;i>=0;i--)
{
if(((res0>>i)&1)||( !flag&&!((z>>i)&1) ) || !((res1>>i)&1) )
{
unsigned long long tt = (res0>>i)&1;
ans |= tt<<i;if((z>>i)&1)flag=1;
continue;
}
if( flag||((z>>i)&1) )
{
unsigned long long tt = (res1>>i)&1;
ans |= tt<<i;
}
}
return ans;
}
int otp[N];
unsigned long long a[N];
int main(){
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=n;i++)scanf("%d%llu",otp+i,a+i);
for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),add(y,x),add(x,y);
dfs(1,0);ddfs(1,1);
for(int i=1;i<=n;i++)modify(1,1,n,nid[i],a[i],otp[i]);
for(int i=1,op,x,y;i<=n;i++)
{
unsigned long long z;
scanf("%d%d%d%llu",&op,&x,&y,&z);
if(op==1)printf("%llu\n",gets(x,y,z));
else modify(1,1,n,nid[x],z,y);
}
}