BZOJ_3589_动态树_容斥原理+树链剖分

题意:

维护一棵树,支持1.子树内点权加上一个数  2.给出k条链,求路径上的点权和(重复的计算一次) (k<=5)

分析:

可以用树剖+线段树解决第一个操作

然后我们发现k非常小,可以二进制枚举

那就容斥一下转化成求几条链的交

链交求法:链顶是两条链顶深度大的那个,链底是两个链底的lca

如果链底深度小于链顶,就说明两条链没有交集

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 200050
#define LL long long
#define ls p<<1
#define rs p<<1|1
int head[N],to[N<<1],nxt[N<<1],cnt,n,q,xx[10],yy[10];
int fa[N],dep[N],top[N],siz[N],son[N],idx[N],tot,k;
int _count[100],strtop[10],strbot[10];
LL mod=2147483648ll;
LL t[N<<2],add[N<<2];
inline void adde(int u,int v){
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
void dfs1(int x,int y){
int i;
fa[x]=y;dep[x]=y+1;
siz[x]=1;
for(i=head[x];i;i=nxt[i]){
if(to[i]!=y){
dfs1(to[i],x);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]])son[x]=to[i];
}
}
}
void dfs2(int x,int t){
top[x]=t;idx[x]=++tot;
int i;
if(son[x]) dfs2(son[x],t);
for(i=head[x];i;i=nxt[i]){
if(to[i]!=fa[x]&&to[i]!=son[x]){
dfs2(to[i],to[i]);
}
}
}
void pud(int l,int r,int p){
if(add[p]==0)return ;
add[ls]+=add[p];
add[ls]%=mod;
add[rs]+=add[p];
add[rs]%=mod;
int mid=l+r>>1;
t[ls]+=add[p]*(mid-l+1);
t[ls]%=mod;
t[rs]+=add[p]*(r-mid);
t[rs]%=mod;
add[p]=0;
}
void update(int l,int r,int x,int y,int c,int p){
if(x<=l&&y>=r){
t[p]+=1ll*c*(r-l+1);
add[p]+=c;
t[p]%=mod;
add[p]%=mod;
return ;
}
pud(l,r,p);
int mid=l+r>>1;
if(x<=mid)update(l,mid,x,y,c,ls);
if(y>mid)update(mid+1,r,x,y,c,rs);
t[p]=t[ls]+t[rs];
t[p]%=mod;
}
LL query(int l,int r,int x,int y,int p){
if(x<=l&&y>=r) return t[p];
int mid=l+r>>1;
LL re=0;
pud(l,r,p);
t[p]=t[ls]+t[rs];
t[p]%=mod;
if(x<=mid)re=(re+query(l,mid,x,y,ls))%mod;
if(y>mid)re=(re+query(mid+1,r,x,y,rs))%mod;
return re%mod;
}
LL ask(int x,int y){
LL re=0;
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]])swap(x,y);
re+=query(1,n,idx[top[y]],idx[y],1);
re%=mod;
y=fa[top[y]];
}
if(dep[x]<dep[y])swap(x,y);
return (re+query(1,n,idx[y],idx[x],1))%mod;
}
void fix(int x,int c){
update(1,n,idx[x],idx[x]+siz[x]-1,c,1);
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]])swap(x,y);
y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
void solve(){
int mask=(1<<k)-1;
int i,flg,j;
LL ans=0;
for(i=1;i<=k;i++){
if(dep[xx[i]]>dep[yy[i]])swap(xx[i],yy[i]);
strtop[i]=xx[i];strbot[i]=yy[i];
}
for(i=1;i<=mask;i++){
if((_count[i]&1))flg=1;
else flg=-1;
int no_jiao=0;
int top_a=0,bot_a=0;
for(j=1;j<=k;j++){
if(i&(1<<j-1)){
if(!top_a){
top_a=strtop[j];
bot_a=strbot[j];
}
else {
bot_a=lca(bot_a,strbot[j]);
if(dep[top_a]<dep[strtop[j]]){
top_a=strtop[j];
}
if(dep[top_a]>dep[bot_a])no_jiao=1;
}
}
}
if(no_jiao)continue;
ans+=flg*ask(top_a,bot_a);
ans=(ans+mod)%mod;
}
printf("%lld\n",ans);
}
int main(){
scanf("%d",&n);
int i,x,y,opt,j;
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
adde(x,y);adde(y,x);
}
dfs1(1,0);
dfs2(1,1);
for(i=1;i<=32;i++){
_count[i]=_count[i>>1]+(i&1);
}
scanf("%d",&q);
while(q--){
scanf("%d",&opt);
if(opt){
scanf("%d",&k);
for(j=1;j<=k;j++){
scanf("%d%d",&xx[j],&yy[j]);
}
solve();
}else{
scanf("%d%d",&x,&y);
fix(x,y);
}
}
}

BZOJ_3589_动态树_容斥原理+树链剖分的更多相关文章

  1. 树的统计Count---树链剖分

    NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...

  2. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  3. BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 23015  Solved: 9336[Submit ...

  4. [bzoj2733][HNOI2012]永无乡_权值线段树_线段树合并

    永无乡 bzoj-2733 HNOI-2012 题目大意:题目链接. 注释:略. 想法: 它的查询操作非常友善,就是一个联通块内的$k$小值. 故此我们可以考虑每个联通块建一棵权值线段树. 这样的话每 ...

  5. 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树

    经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...

  6. 219.01.19 bzoj3252: 攻略(长链剖分+贪心)

    传送门 长链剖分好题. 题意:给一棵带点权的树,可以从根节点到任一叶节点走kkk次,走过的点只能计算一次,问kkk次走过的点点权值和最大值. 思路: 考虑将整棵树带权长链剖分,这样链与链之间是不会重复 ...

  7. 【BZOJ-3589】动态树 树链剖分 + 线段树 + 线段覆盖(特殊的技巧)

    3589: 动态树 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 405  Solved: 137[Submit][Status][Discuss] ...

  8. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  9. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

随机推荐

  1. 实例解析Collections源码,Iterator和ListIterator

    比如一个视频或文章有多个页面标签设置,我们在看一篇文章或一个视频时,底部有为你推荐栏目. 如何根据这个文章或视频的标签,来实现这个推荐栏目呢. public List<VideoInfoVo&g ...

  2. 了解与建设有中国特色的Android M&N(Android6.0和7.0新特性分析)

    http://geek.csdn.NET/news/detail/110434 Android N已经发布有段时间,甚至马上都要发布android 7.1,相信不少玩机爱好者已经刷入最新的Androi ...

  3. 使用AngularJS开发中的几个问题

    1.AngularJS的模板绑定机制好像和其$http服务也有一定关系,如果用jQuery Ajax的返回值赋给$scope的作用域变量,整个绑定显示的节奏慢一个事件,神器果然麻烦啊. 2.对hidd ...

  4. 基于Kurento的WebRTC移动视频群聊技术方案

    说在前面的话:视频实时群聊天有三种架构: Mesh架构:终端之间互相连接,没有中心服务器,产生的问题,每个终端都要连接n-1个终端,每个终端的编码和网络压力都很大.群聊人数N不可能太大. Router ...

  5. android下ViewPager的使用,带下部选项栏的切换动画

    (文章针对类似我这种初学者,大神看到不要嘲笑) 演示 我的规矩是先上GIF动画效果(Linux下用转的GIF,清晰度还可以但是不知道为什么放博客上,界面会这么大): 代码: android中有View ...

  6. 终端字形logo

    网上有很多的项目都有一个自己的字形logo,而我也在开发一个小的项目,也想要生成一个终端字形的logo,于是找到这款小工具,分享给大家:FIGlet “FIGlet is a program for ...

  7. Spark---架构原理

    Spark核心组件 1.Driver 我们编写的Spark程序就在Driver上 Spark集群节点之一,就是你提交的Spark程序的机器 2.Master Master是个进程 Master其实主要 ...

  8. Java虚拟机-内存tips

    java虚拟机内存可以分为独占区和共享区. 独占区:虚拟内存栈.本地方法栈.程序计数器. 共享区:方法区.Java堆(用来存放对象实例). 程序计数器 比较小的内存空间,当前线程所执行的字节码的行号指 ...

  9. php中的抽象方法和抽象类,简单明了,一点通

    1.什么是抽象方法?    我们在类里面定义的没有方法提的方法就是抽象方法.所谓的没有方法体指的是,在声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象方法时方 ...

  10. 拾人牙慧篇之———QQ微信的第三方登录实现

    一.写在前面 关于qq微信登录的原理之流我就不一一赘述了,对应的官网都有,在这里主要是展示我是怎么实现出来的,看了好几个博客,有的是直接复制官网的,有的不知道为什么实现不了.我只能保证我的这个是我实现 ...