线段树合并+树上差分

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

考试时想法看>这里<

总思路:先存所有的操作,离散化,然后用树上差分解决修改,用权值线段树维护每个值的个数,最后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. 15.oauth2 + oidc 实现 server部分

    OAuth主要做授权. OpenIdConnect简历在OAuth2.0基础之上的,相结合 客户端.授权中心.Resource Owner用户本身(资源的拥有者).Resource Server 通过 ...

  2. 转载 关于启用HTTPS的一些经验分享

    本文转载自  https://imququ.com/post/sth-about-switch-to-https.html 随着国内网络环境的持续恶化,各种篡改和劫持层出不穷,越来越多的网站选择了全站 ...

  3. UVaLive 2965 Jurassic Remains (状态压缩)

    题意:给定 n 个大写字母组成的字符串,选择尽量多的串,使得大写字母都能出现偶数次. 析:由于n比较小,我们可以枚举前n/2的所有组合,然后再从后面查找. 代码如下: #pragma comment( ...

  4. ios NSFileManager创建目录、文件

    NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *str1 = NSHomeDirectory(); _fi ...

  5. Qt中csv文件的导入与导出

    转自:http://blog.csdn.net/mingxia_sui/article/details/7683030 CSV 1.简介: 全称:Comma Separated Values. 是“逗 ...

  6. HDU2824【欧拉函数性质】

    思路: 打表. 利用公式. 类似素数打表一样. #include<bits/stdc++.h> using namespace std; const int N=3e6+10; bool ...

  7. hdoj5875【二分+RMQ】

    全部从我大哥那里学习得来.. 一开始硬着头皮就是根据思路上线段树,明知是T还要写(因为线段树还不是很熟,趁机练一发) 后来果然T了,然后就去学了一发RMQ的ST算法,查询是O(1). ST算法主要: ...

  8. wow.js零基础使用介绍

    wow.js依赖于animate.css,首先需要在 head内引入animate.css或者animate.min.css wow.js或者wow.min.js,然后js文件里再写一行代码. 然后在 ...

  9. IDEA 快捷键MacOS

    Alt + Enter 导入包,自动修正 Command + N 查找类 Command + Shift + N查找文件 Command + Alt + L格式化代码 Command + Alt + ...

  10. AFHTTPSessionManager下载文件 及下载中 进度条处理,进度条处理需要特别注意,要加载NSRunLoop 中

    1.下载文件 和进度条处理代码 - (void)timer:(NSTimer *)timer{ // 另一个View中 进度条progress属性赋值 _downloadView.progress = ...