LYK loves games

2024-03-16 23:08
文章标签 games loves lyk

本文主要是介绍LYK loves games,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

LYK loves games

题解

还是挺简单的。

首先 O ( n q l o g n ) O\left(nqlog\,n\right) O(nqlogn)的做法应该是很好想到的,可以树dp,考虑对每个 v a l i val_{i} vali进行二进制拆分,对于每一位单独进行处理,这样的话异或就比较好操作了。
我们每次只需要合并点 u , v u,v u,v时将两个当前位置不同的方案数乘起来再乘上当前位的大小即可。
设点 u u u i i i位为 0 , 1 0,1 0,1时的方案数为 s u m u , i , 0 / 1 sum_{u,i,0/1} sumu,i,0/1,只需要让 a n s + = 2 i s u m u , i , 0 / 1 s u m u , i , 1 / 0 ans+=2^isum_{u,i,0/1}sum_{u,i,1/0} ans+=2isumu,i,0/1sumu,i,1/0即可。

但是这样做的话每次修改时都要再对一条链上的点进行合并,时间复杂度达到了 O ( n q l o g n ) O\left(nqlog\,n\right) O(nqlogn),不随机的最后20pts是过不了的。
考虑建点分树,减少树的深度。
我们把点分树建出来后,需要建一棵线段树来维护子树中的点到它这里路径当前位异或值为 0 / 1 0/1 0/1的方案数。
我们只需要维护修改,查询与 0 / 1 0/1 0/1翻转这三个操作,
时间复杂度就这样被降到 O ( n l o g 2 n ) O\left(nlog^2n\right) O(nlog2n)

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 10005
const int INF=0x7f7f7f7f;
typedef long long LL;
typedef pair<int,int> pii;
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while('0'>s||s>'9'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
int n,q,val[MAXN],head[MAXN],tot,dep[MAXN],dfn[20][MAXN];
int siz[20][MAXN],A[20][2],B[20][2],bel[20][MAXN],tim[MAXN];
int all[MAXN],num[MAXN][20],father[MAXN];LL ans;bool vis[MAXN];
struct edge{int to,nxt;}e[MAXN<<1];
void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
pii operator + (const pii &a,const pii &b){return make_pair(a.first+b.first,a.second+b.second);}
pii operator - (const pii &a,const pii &b){return make_pair(a.first-b.first,a.second-b.second);}
struct segmentTree{#define lson (rt<<1)#define rson (rt<<1|1)int sum[MAXN<<2][2];bool rev[MAXN<<2];void updata(int rt){sum[rt][0]=sum[lson][0]+sum[rson][0];sum[rt][1]=sum[lson][1]+sum[rson][1];}void downdata(int rt){if(!rev[rt])return ;rev[rt]=0;swap(sum[lson][0],sum[lson][1]);rev[lson]^=1;swap(sum[rson][0],sum[rson][1]);rev[rson]^=1;}void insert(int rt,int l,int r,int ai,int aw){if(l>r||l>ai||r<ai)return ;int mid=l+r>>1;if(l==r){sum[rt][aw]++;return ;}if(ai<=mid)insert(lson,l,mid,ai,aw);else insert(rson,mid+1,r,ai,aw);updata(rt);}void Reverse(int rt,int l,int r,int al,int ar){if(l>r||al>r||ar<l)return ;if(al<=l&&r<=ar){swap(sum[rt][0],sum[rt][1]);rev[rt]^=1;return ;}int mid=l+r>>1;downdata(rt);if(al<=mid)Reverse(lson,l,mid,al,ar);if(ar>mid)Reverse(rson,mid+1,r,al,ar);updata(rt);}pii query(int rt,int l,int r,int al,int ar){if(l>r||al>r||ar<l)return make_pair(0,0);int mid=l+r>>1;if(al<=l&&r<=ar)return make_pair(sum[rt][0],sum[rt][1]);pii res=make_pair(0,0);downdata(rt);if(al<=mid)res=res+query(lson,l,mid,al,ar);if(ar>mid)res=res+query(rson,mid+1,r,al,ar);return res;}
}T[20][20];
void dosaka(int u,int fa,int p,int x){int d=dep[p];bel[d][u]=(fa==p)?u:bel[d][fa];dfn[d][u]=++tim[d];siz[d][u]=1;x^=val[u];for(int i=0;i<15;i++)B[i][x>>i&1]++,T[d][i].insert(1,1,n,tim[d],x>>i&1);for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(vis[v]||v==fa)continue;dosaka(v,u,p,x);siz[d][u]+=siz[d][v];}
}
int getRoot(int u,int fa,int Sz,int &g){int sz=1,tmp;bool flag=1;for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(vis[v]||v==fa)continue;sz+=(tmp=getRoot(v,u,Sz,g));flag&=tmp<<1<=Sz;}if(flag&&(Sz-sz)<<1<=Sz)g=u;return sz;
}
int sakura(int u,int Sz,int dp){getRoot(u,0,Sz,u);vis[u]=1;dep[u]=dp;dfn[dp][u]=++tim[dp];siz[dp][u]=1;memset(B,0,sizeof B);//printf("sakura %d:%d %d %d\n",u,dep[u],dfn[dp][u],siz[dp][u]);for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(vis[v])continue;memcpy(A,B,sizeof B);dosaka(v,u,u,0);all[u]+=siz[dp][u]*siz[dp][v];siz[dp][u]+=siz[dp][v];for(int i=0;i<15;i++){int x=val[u]>>i&1,tmp=(B[i][0]-A[i][0])*A[i][!x]+(B[i][1]-A[i][1])*A[i][x]+B[i][!x]-A[i][!x];num[u][i]+=tmp;ans+=(1LL<<i)*tmp;}}for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(vis[v])continue;father[sakura(v,siz[dp][v],dp+1)]=u;}return u;
}
void solve(int x,int now){int pre=val[x];val[x]=now;for(int i=0;i<15;i++){if((now>>i&1)==(pre>>i&1))continue;ans-=num[x][i]*(1LL<<i);num[x][i]=all[x]-num[x][i];ans+=num[x][i]*(1LL<<i);}for(int u=father[x];u;u=father[u])for(int i=0,d=dep[u];i<15;i++){if((now>>i&1)==(pre>>i&1))continue;bool t=val[u]>>i&1;pii sx,su;sx=T[d][i].query(1,1,n,dfn[d][x],dfn[d][x]+siz[d][x]-1);su=T[d][i].query(1,1,n,dfn[d][u]+1,dfn[d][u]+siz[d][u]-1)-T[d][i].query(1,1,n,dfn[d][bel[d][x]],dfn[d][bel[d][x]]+siz[d][bel[d][x]]-1);T[d][i].Reverse(1,1,n,dfn[d][x],dfn[d][x]+siz[d][x]-1);//printf("solve %d %d %d %d %d:%d %d %d %d\n",u,i,dfn[d][u],siz[d][u],bel[d][x],sx.first,sx.second,su.first,su.second);int dt=su.first*(!t?(sx.first-sx.second):(sx.second-sx.first))+su.second*(!t?(sx.second-sx.first):(sx.first-sx.second))+(!t?(sx.first-sx.second):(sx.second-sx.first));num[u][i]+=dt;ans+=dt*(1ll<<i);}
}
int main(){//freopen("games.in","r",stdin);//freopen("games.out","w",stdout);read(n);read(q);for(int i=1;i<=n;i++)read(val[i]);for(int i=1;i<n;i++){int u,v;read(u);read(v);addEdge(u,v);addEdge(v,u);}sakura(1,n,0);while(q--){int l,r;read(l);read(r);solve(l,r);printf("%lld\n",ans<<1);}return 0;
}

谢谢!!!

这篇关于LYK loves games的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/817025

相关文章

【HDU】4876 ZCC loves cards 暴力

传送门:【HDU】4876 ZCC loves cards 题目分析: 这题无力吐嘈。。。。能想到的优化都用上吧。。。 代码如下: #include <cstdio>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , n ) for ( int i =

【HDU】4873 ZCC Loves Intersection 数学

传送门:【HDU】4873 ZCC Loves Intersection 题目大意:给你一个D维的空间,每个维度都有一条线段平行与该维度属于的轴(如X,Y,Z轴),且线段的端点坐标取值范围0~N-1,保证左端点严格小于右端点(除该维度,其他维度的值两端点均相等)。现在告诉你每条线段的左右端点的坐标都是随机的,0~N-1随机到的概率是完全相等的!现在如果两条线段如果相交于一点,你可以获得一点

【HDU】5197 DZY Loves Orzing 【FFT启发式合并】

传送门:【HDU】5197 DZY Loves Orzing 题目分析: 首先申明,我不会 dp dp方程= =……这个东西给队友找出来了,然后我就是套这个方程做题的Qrz…… 对于这题,因为 n2 n^2个数互不相同,所以每一列都可以单独考虑。设 dpni dp_ni表示长度为 n n的排列,能恰好看见ii个人的方案数,根据队友的发现, dpni dp_ni就等于 |sni| |s_ni|

Codeforces Round #FF (Div. 2/C)/Codeforces446A_DZY Loves Sequences(DP)

DZY Loves Sequences time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output DZY has a sequence a, consisting of n integers. We'

Codeforces Round #FF (Div. 2/A)/Codeforces447A_DZY Loves Hash(哈希)

A. DZY Loves Hash time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output DZY has a hash table with p buckets, numbered from

D. DZY Loves Modification

D. DZY Loves Modification time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output As we know, DZY loves playing games. One da

世链投研| Gala Games横空出世,被高赞“做出了链游该有的样子”。

在区块链领域,是否拥有足够基数的用户是衡量一个项目是否成功的重要指标。而到了区块链游戏这一具体赛道,就更是如此。谁能拥有足够多忠诚度高,活跃度高,粘着性强的游戏玩家,谁就能在链游领域立于不败之地。 而Gala Games,恰恰凭借着超高人气和火爆程度成为了链游领域及NFT风口之上的弄潮儿。 Gala Games致力于成为一个去中心化的游戏社交平台,在不断进步,不断精进内容的道路上,始终不断华丽

hdu5274 Dylans loves tree

官方题解 题目里有一个很神奇的性质:路径上最多只有一个数出现奇数次。这应该马上想到异或。因为异或两次和没异或是等价的。此外异或满足区间减性质。因为有修改,我们很自然地想到用数据结构维护。最无脑的就是直接上树链剖分或是Splay维护区间xor值即可。仔细想一想,发现可以利用LCA消去“树上路径”,转化为根到x路径上求xor值。我们可以很经典地直接使用线段树或树状数组维护dfs序。(然而

hdu5196 DZY Loves Inversions 思路,计数

题意:一个数列,给出一些区间,计算这个区间有多少子区间逆序对数为k。 分析:直接计算k不好算,把问题转化为<=k的子区间数减去<k的子区间数。首先由两个指针可以求出每一个点的满足<=k或<k的最右边界。得到r1和r2数组。    最后所求即为sum(min(r1i,r)-l+1) (i>=l&&i<=r),r数组单调递增,二分即可。 #include<iostream>#include

codeforces#FF DIV2C题DZY Loves Sequences(DP)

题目地址:http://codeforces.com/contest/447/problem/C C. DZY Loves Sequences time limit per test 1 second memory limit per test 256 megabytes input standard input output standard outpu