线段树合并+树上差分

题目链接(···) 「简单」「一般」——其实「一般」也只多一个离散化

考试时想法看>这里<

总思路:先存所有的操作,离散化,然后用树上差分解决修改,用权值线段树维护每个值的个数,最后dfs合并处理答案(先处理儿子,再合并自己和儿子,递归解决)

简单版当然不用离散话辣。

做了好几天,感觉自己傻了。

但是好像也不是这样的

事实上,这道题确实扩充了我对线段树的认识。

它它它还可以不存左右区间的啊?——一定是我太蒻了

先附样例以示敬意


Sample Input


Sample Output

我还是第一次见这么恐怖的样例

不过它也是我的救命稻草,让我骗了5分,这是之前的事

样例以1为根的巨树

还是能看下的

树上差分就是通过修改树上某些节点的值来修改一段区间值的方法,比较常用

比如我们需要加树上一个区间

想这样,加从3到4的区间,每个加1(加N也一样)

那么我们按照差分法,3++,4++,1--,2--

「公式」其实是 x+n ,y+n ,lca(x,y)-n ,father[lca(x,y)]-n

别告诉我你不会lca,虽然我也是刚学了实用的版本

结果是这样的

这一步很快的···

我们要的结果当然不是±1什么的,要的是1或0

所以下面就是dfs统计结果(‘=’号前是过程,‘=’后是结果)

仿佛得到了结果

这样我们就能够离线处理树上的区间加减

注意:只能是离线,N个修改,一次输出


线段树合并前面已经说过,这里不再细讲。

这个题仿佛对内存的限制很苛刻(我MLE 22 次,数过,想哭),所以线段树的节点一定要节约开空,只开最大值和左右儿子指针

//鬼知道我调了几天的是这个傻点

左右区间可以递归维护,不必要一定存在节点里,

也不必须在维护最大值时捆绑维护下标,查询时的O(NlogN)还是可以接受的

 #include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <queue>
#define N 200001
#define B 2*N
#define logN 31
using namespace std;
struct ST{
int f,t,next;
};ST rs[B];
int tot=,fl[N],n,m,len;
void add(int f,int t){
rs[tot].f=f;
rs[tot].t=t;
rs[tot].next=fl[f];
fl[f]=tot;
tot++;
}
struct XDS{
XDS *lid,*rid;
int maxn;
XDS(){
lid=rid=NULL;
maxn=;
}
};XDS *root[N];
struct CON{
int x,y,z;
};CON q[N];
int val[N];
int fvind(int i){
return lower_bound(val,val+len,i)-val+;
}
inline void build(XDS *&n){
n=new XDS();
}
void add(XDS *&rt,int v,int k,int l,int r){
if(rt==NULL)build(rt);
if(l==r){
rt->maxn+=k;
return ;
}
int mid=(l+r)>>;
if(mid>=v){
add(rt->lid,v,k,l,mid);
}
else{
add(rt->rid,v,k,mid+,r);
}
if(rt->lid!=NULL){
rt->maxn = rt->lid->maxn;
}
if(rt->rid!=NULL&&
rt->maxn < rt->rid->maxn)
rt->maxn = rt->rid->maxn;
}
int dep[N],fa[N][logN],ln;
bool is_v[N];
struct Myqu{
int f,e;
int Q[N*];
void push(int k){
e++;
Q[e]=k;
}
int front(){
f++;
return Q[f];
}
bool empty(){
if(e==f)return true;
return false;
}
}qu;
void bfs(int k){
qu.push(k);
is_v[k]=;
while(!qu.empty()){
int f=qu.front();
for(int i=fl[f];i!=-;i=rs[i].next){
if(!is_v[rs[i].t]){
qu.push(rs[i].t);
is_v[rs[i].t]=;
fa[rs[i].t][]=f;
dep[rs[i].t]=dep[f]+;
for(int j=;j<=ln;j++) fa[rs[i].t][j]=fa[fa[rs[i].t][j-]][j-];
}
}
}
}
int lca(int a,int b){//cout<<a<<SP<<b<<endl;
if(dep[a]>dep[b])swap(a,b);
for(int i=ln;i>=;i--)
if(dep[fa[b][i]]>=dep[a]){
b=fa[b][i];
//cout<<" "<<b<<" Dep"<<dep[b]<<endl;
}
if(a==b) return b;
for(int i=ln;i>=;i--)
if(fa[a][i]!=fa[b][i]){
a=fa[a][i],b=fa[b][i];
}
return fa[a][];
}
XDS* merge(int l,int r,XDS *&a,XDS *&b){
if(a==NULL)return b;
if(b==NULL)return a;
if(l==r){
a->maxn =a->maxn+b->maxn;
delete b;
b=NULL;
return a;
}
int mid=(l+r)>>;//puts("midgot");
a->lid=merge(l,mid,a->lid,b->lid);//puts("Lid merge end");
a->rid=merge(mid+,r,a->rid,b->rid);
if(a->lid!=NULL){
a->maxn = a->lid->maxn;
}
if(a->rid!=NULL&&
a->rid->maxn > a->maxn)
a->maxn =a->rid->maxn;
return a;
}
int ffind(XDS *rt,int l,int r){
int mid=(l+r)>>;
if(rt==NULL)return -;
if(l==r)return l;
if(rt->lid==NULL&&rt->rid==NULL)return -;
if(rt->lid==NULL)return ffind(rt->rid,mid+,r);
if(rt->rid==NULL)return ffind(rt->lid,l,mid);
if(rt->lid->maxn>=rt->rid->maxn){
return ffind(rt->lid,l,mid);
}
else return ffind(rt->rid,mid+,r);
}
void getans(int k){
is_v[k]=;
for(int i=fl[k];i!=-;i=rs[i].next){
if(is_v[rs[i].t]){
getans(rs[i].t);
root[k]=merge(,len,root[k],root[rs[i].t]);
}
}
int q=ffind(root[k],,len);
if(q==-)dep[k]=;
else dep[k]=val[q-];
}
int du[N];
int main(){
int a,b,c,ro;
memset(fl ,-,sizeof fl);
scanf("%d%d",&n,&m);
ln=log2(n)+;
for(int i=;i<n;i++){
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
for(int i=;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
q[i].x=a ,q[i].y=b ,q[i].z=val[i-]=c;
du[a]++,du[b]++;
}
int maxn=-;
for(int i=;i<=n;i++){
if(du[i]>maxn){
ro=i;
maxn=du[i];
}
}
sort(val+,val+m);
len=unique(val,val+m)-val;
dep[ro]=;
bfs(ro);
for(int i=;i<=m;i++){
int Lca=lca(q[i].x,q[i].y),val=fvind(q[i].z);
add(root[Lca], val,-,,len);
add(root[fa[Lca][]],val,-,,len);
add(root[q[i].x] ,val, ,,len);
add(root[q[i].y] ,val, ,,len);
}
getans(ro);
for(int i=;i<=n;i++){
printf("%d\n",dep[i]);
}
return ;
}

Total Code

[洛谷P4556][BZOJ3307]雨天的尾巴-T3订正的更多相关文章

  1. 【洛谷P4556】 雨天的尾巴

    题面 题解 线段树合并 我们看到这道题目首先可以想到树上差分,然后\(dfs\)合并 发现题目让我们求的东西很好用线段树维护 于是可以想到线段树合并 全世界只有我写指针版动态开点线段树(大雾 如果你要 ...

  2. 洛谷P4556 雨天的尾巴(线段树合并)

    洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...

  3. [洛谷P4556] 雨天的尾巴

    这道题可以用线段树合并做,网上的题解基本上都是线段树合并的. 但是为什么我就偏偏要用dsu on tree...... 题目传送门 dsu on tree的方法类似[CF1009F] Dominant ...

  4. [BZOJ3307] 雨天的尾巴(树上差分+线段树合并)

    [BZOJ3307] 雨天的尾巴(树上差分+线段树合并) 题面 给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型. N, M≤100000 分析 ...

  5. 洛谷 P4556 [Vani有约会]雨天的尾巴 解题报告

    P4556 [Vani有约会]雨天的尾巴 题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒 ...

  6. [bzoj3307]雨天的尾巴_线段树合并

    雨天的尾巴 bzoj-3307 题目大意:N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. ...

  7. 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)

    题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...

  8. 洛谷P4556 雨天的尾巴 线段树

    正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...

  9. 2018.08.28 洛谷P4556 [Vani有约会]雨天的尾巴(树上差分+线段树合并)

    传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h& ...

随机推荐

  1. python-os.walk()使用举例

    文件目录结构 dir 1 1 1.txt 2.txt 3.txt 2 2.txt 3 4 4.txt 3.txt 1.txt 2 2.txt 3 3.txt dir.txt 代码: import os ...

  2. 51nod 1051【基础】

    思路: 找题4级做做...然后找了题最水的.. = =感动...居然是一下子[记]得了做法... dp一下,枚举列的起点和终点,然后求和这一段,然后对这一大列就是求个最大字段和: #include & ...

  3. unity常用插件

    Unity3D常用插件,网址:http://jingyan.baidu.com/article/7f766daf4ef2844100e1d079.html ,想想自己也有小半年unity经验了,于是整 ...

  4. [Xcode 实际操作]三、视图控制器-(1)使用UIScrollView展示多个视图可控制器

    目录:[Swift]Xcode实际操作 本文将演示使用滚动视图创建多个页面. [Create a new Xcode project]->[Single View App]->[Next] ...

  5. DOM0、DOM2级事件

    JavaScript DOM0.DOM2级事件 1.DOM0级事件:on+事件类型 在html行内直接绑定,也就是通过行内js绑定的例如<span onclick="alert('1' ...

  6. hyperledger fabric 1.0.5 分布式部署 (一)

    环境是个人虚拟机ubuntu 16.04 64 位版本 前期用户需要先安装好:gcc.g++.git 软件 安装 golang 首先给环境安装一个 go 语言环境,版本最好在1.8 以上 golang ...

  7. SQL COUNT DISTINCT 函数

    定义和用法 可以一同使用 DISTINCT 和 COUNT 关键词,来计算非重复结果的数目. 语法 SELECT COUNT(DISTINCT column(s)) FROM table 例子 注意: ...

  8. servlet小型应用服务器搭建通过tomcat发布web项目

    1.servlet简介:Servlet 是一个 Java程序,是在服务器上运行以处理客户端请求并做出响应的程序 2.servlet的生命周期图解: 3.各阶段: 4.基本的servlet代码: pub ...

  9. #10:wannanewtry——6

    HDU3401,列完转移方程拆分一下,正着.反着跑优先队列优化代表买或卖.初始化不大会搞…… #include <bits/stdc++.h> using namespace std; c ...

  10. siege官方文档(译)(二)

    WHY DO I NEED IT? Siege was written for both web developers and web systems administrators. siege是为了 ...