bzoj3589 动态树
题意:给你一棵树,要求你维护两个操作.
0:某子树的所有节点权值加上一个数.
1:求某些链并集的权值和.
对于第一个操作,大力树链剖分加线段树.
对于第二个操作,考虑到链的数量很少,可以容斥.
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iomanip>
using namespace std;
#define LL long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define pii pair<int,int>
#define db double
#define eps 1e-4
#define FILE "dealing"
int read(){int x=0,f=1,ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}return x*f;
}
const LL maxn=1000000,inf=1000000000000000LL,limit=20000;
bool cmin(int& a,int b){return a>b?a=b,true:false;}
bool cmax(int& a,int b){return a<b?a=b,true:false;}
int n,m;
struct node{int y,next;
}e[maxn];
int len=0,linkk[maxn],top[maxn],fa[maxn],dep[maxn],pre[maxn],low[maxn];
void insert(int x,int y){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;
}
void init(){n=read();up(i,1,n-1){int x=read(),y=read();insert(x,y);insert(y,x);}
}
namespace treepou{int dfs_clock=0,siz[maxn],son[maxn];void dfs1(int x){siz[x]=1;for(int i=linkk[x];i;i=e[i].next){if(e[i].y==fa[x])continue;fa[e[i].y]=x;dep[e[i].y]=dep[x]+1;dfs1(e[i].y);siz[x]+=siz[e[i].y];if(siz[e[i].y]>siz[son[x]])son[x]=e[i].y;}}void dfs2(int x){pre[x]=++dfs_clock;if(son[x]){top[son[x]]=top[x];dfs2(son[x]);}for(int i=linkk[x];i;i=e[i].next){if(e[i].y==son[x]||e[i].y==fa[x])continue;top[e[i].y]=e[i].y;dfs2(e[i].y);}low[x]=dfs_clock;}void solve(){dfs1(1);top[1]=1;dfs2(1);}
};
namespace SegTree{int del[maxn],siz[maxn],sum[maxn],L,R,key,id[maxn];int Add(int x,int d){del[x]+=d;sum[x]+=siz[x]*d;}void updata(int x){sum[x]=sum[x<<1]+sum[x<<1|1];}void pushdown(int x){if(del[x]){Add(x<<1,del[x]);Add(x<<1|1,del[x]);del[x]=0;}}void change(int o,int l,int r){if(l>R||r<L)return;if(l>=L&&r<=R){Add(o,key);return;}int mid=(l+r)>>1;pushdown(o);change(o<<1,l,mid);change(o<<1|1,mid+1,r);updata(o);}void Change(int x,int y,int Del){L=x,R=y,key=Del;change(1,1,n);}int query(int l,int r,int o){if(l>R||r<L)return 0;if(l>=L&&r<=R)return sum[o];int mid=(l+r)>>1;pushdown(o);return query(l,mid,o<<1)+query(mid+1,r,o<<1|1);}int Query(int x,int y){if(x>y)swap(x,y);L=x,R=y;return query(1,n,1);}void build(int l,int r,int o){if(l==r){siz[o]=1;sum[o]=0;return;}int mid=(l+r)>>1;build(l,mid,o<<1);build(mid+1,r,o<<1|1);siz[o]=siz[o<<1]+siz[o<<1|1];}void Build(){up(i,1,n)id[pre[i]]=i;build(1,n,1);}
}
namespace solve{pii getlian(int x,int y){int f1,f2;int sum=0;while(true){if(dep[x]>dep[y])swap(x,y);f1=top[x],f2=top[y];if(f1==f2){sum+=SegTree::Query(pre[x],pre[y]);return make_pair(x,sum);}if(dep[f1]>dep[f2])swap(x,y),swap(f1,f2);sum+=SegTree::Query(pre[f2],pre[y]);y=fa[f2];}}int getlca(int x,int y){int f1,f2;while(true){if(dep[x]>dep[y])swap(x,y);f1=top[x],f2=top[y];if(f1==f2)return x;if(dep[f1]>dep[f2])swap(x,y),swap(f1,f2);y=fa[f2];}}pii t[maxn];int query(){int m=read();up(i,1,m){t[i].first=read(),t[i].second=read();if(dep[t[i].first]>dep[t[i].second])swap(t[i].first,t[i].second);}pii y=make_pair(0,0);int ans=0;for(int i=1;i<(1<<m);i++){int g=-1,flag=0;up(j,1,m){if(i&(1<<j-1))g*=-1;else continue;if(!flag)y=t[j],flag=1;else {int w=getlca(y.second,t[j].second);if(dep[w]<dep[y.first]||dep[w]<dep[t[j].first]){y=make_pair(0,0);break;}else {if(dep[y.first]<dep[t[j].first])y.first=t[j].first;y.second=w;}}}//printf("%d %d %d\n",g,y.first,y.second);if(y.first)ans+=g*getlian(y.first,y.second).second;}return ans;}
};int main(){freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);init();treepou::solve();//树剖 返回top,dep,faSegTree::Build();//prepare SegTree int m=read();while(m--){int ch=read();if(ch==0){int x=read(),del=read();SegTree::Change(pre[x],low[x],del);}else printf("%d\n",solve::query()&((1<<31)-1));}return 0;
}
转载于:https://www.cnblogs.com/chadinblog/p/6492672.html
bzoj3589 动态树相关推荐
- bzoj3589 动态树 求链并 容斥
bzoj3589 动态树 链接 bzoj 思路 求链并. 发现只有最多5条链子,可以容斥. 链交求法:链顶是两条链顶深度大的那个,链底是两个链底的\(lca\) 如果链底深度小于链顶,就说明两条链没有 ...
- BZOJ3589 动态树(树链剖分+容斥原理)
显然容斥后转化为求树链的交.这个题非常良心的保证了查询的路径都是到祖先的,求交就很休闲了. #include<iostream> #include<cstdio> #inclu ...
- 如何利用FineReport制作动态树报表
在对数据字段进行分类管理时,利用动态树折叠数据是一个很好的方法,也就是点击数据前面的加号才展开对应下面的数据,如下图.那这样的效果在制作报表时该如何实现呢? 下面以报表工具FineReport为例介绍 ...
- 【动态树】[BZOJ2002] Bounce 弹飞绵羊
实际上就是动态树的模版加上一个维护每一条链的size这样就可以吧一次弹射看成一条路径,然后统计这个路径上的size实际上就是经过了多少个节点然后没什么了.. #include <bits/std ...
- 【高级数据结构】[SPOJ QTREE]树链剖分/动态树各一模板
题目: 树链剖分: #include<cstdio> #include<cstring> #include<algorithm> using namespace s ...
- 动态树与静态树显示——(一)
常用属性 常用事件: 1.第一种是静态树: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> ...
- P4719 【模板】“动态 DP“动态树分治(矩阵/轻重链剖分/ddp)
P4719 [模板]"动态 DP"&动态树分治 求解树上最大权独立集,但是需要支持修改. https://www.luogu.com.cn/problem/solution ...
- luoguP3690 【模板】Link Cut Tree (动态树)[LCT]
题目背景 动态树 题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- URAL1553 Caves and Tunnels 树链剖分 动态树
URAL1553 维护一棵树,随时修改某个节点的权值,询问(x,y)路径上权值最大的点. 树是静态的,不过套动态树也能过,时限卡的严就得上树链剖分了. 还是那句话 splay的核心是splay(x) ...
最新文章
- ACL 2019 | 基于知识增强的语言表示模型,多项NLP任务表现超越BERT(附论文解读)...
- 博士申请 | 加拿大麦吉尔大学丁俊老师招收机器学习全奖博士/硕士/实习生
- 全自动洗衣机单片机c语言程序,全自动洗衣机单片机程序
- python函数星号参数
- mysql数据库管理系统模式_MYSQL命令行模式管理MySql的一点心得
- js 获取url问号前_收下这波 JS 技巧,从此少加班
- Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级)
- Spring Cloud微服务之Hystrix服务熔断(十二)
- 福大软工1816 · 第二次作业 - 个人项目
- Vue2.x中的父组件数据传递至子组件
- git整合分支的两种方式 merge 和 rebase
- AcWing 1208. 翻硬币
- Git 学习笔记--git 查看某个文件的修改历史
- Json转换为Model,Struct,Class对象 Swift
- 动网论坛 php版,动网即将推出第二代PHP版本论坛系统
- linux下文本去重
- vue+echarts绘制中国地图,动态配置省份颜色和城市标点
- MATLAB全局变量
- CSS 实现元素固定宽高比
- SQL求连续活跃天数