题解:

win下的10mb和linux下的好像不是很一样 明天再看看

求lca用的离线求,注意bz数组开2*n

这道题的线段树合并还是很好想的

我们只要把操作差分一下就好了

时间复杂度nlogn的

写代码用时:1:30

对拍+maker+调错=30

看到网上题解用的是树剖。。

我看了很久很久才理解。。

以前我用树剖都没有去理解它变成序列这个本质。。

树剖保证了区间的连续性,所以差分对于不在同一段的完全没有影响

所以树剖完了就直接变成序列问题,非常强势啊

明天补

这样是nlognlogn的

正解:

#include <bits/stdc++.h>
using namespace std;
#define IL inline
#define rint register int
const int N=1.1e5;
char ss[<<],*A=ss,*B=ss;
IL char gc(){return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;}
template<class T>void read(T&x){
rint f=,c;while(c=gc(),c<||<c)if(c=='-')f=-;x=c^;
while(c=gc(),<c&&c<)x=(x<<)+(x<<)+(c^);x*=f;
}
IL void maxa(int &x,int y)
{
if (x>y) return;
else x=y;
}
IL void mina(int &x,int y)
{
if (x<y) return;
else x=y;
}
IL int max(int x,int y)
{
if (x>y) return(x); else return(y);
}
IL int min(int x,int y)
{
if (x<y) return(x); else return(y);
}
int n,m,fa[N],head[N],fi[N],root[N],cnt,cnt2,l,ans[N];
struct re{
int a,b;
}a[N*],b[N],c[N];
IL void arr(int x,int y)
{
a[++l].a=head[x];
a[l].b=y;
head[x]=l;
}
int id[N],dy[N],bz[][N*],pos[N],vt[N],fdy[N];
vector <int> ve1[N],ve2[N];
void dfs(int x)
{
id[x]=++cnt;
dy[cnt]=x;
bz[][++cnt2]=id[x];
pos[x]=cnt2;
int u=head[x];
while (u)
{
int v=a[u].b;
if (v!=fa[x])
{
fa[v]=x;
dfs(v);
bz[][++cnt2]=id[x];
}
u=a[u].a;
}
}
IL void swap(int &x,int &y)
{
int z=x; x=y; y=z;
}
IL int lca(int x,int y)
{
if (x==y) return(x);
x=pos[x],y=pos[y];
if (x>y) swap(x,y);
int z=log2(y-x+);
return(dy[min(bz[z][x],bz[z][y-(<<z)+])]);
}
struct segementree
{
int cnt;
int v[N*],p[N*],ls[N*],rs[N*];
segementree() { cnt=; }
#define mid ((h+t)/2)
IL void updata(int x)
{
v[x]=max(v[ls[x]],v[rs[x]]);
if (v[ls[x]]>v[rs[x]]||(v[ls[x]]==v[rs[x]]&&p[ls[x]]<p[rs[x]]))
p[x]=p[ls[x]];
else p[x]=p[rs[x]];
}
void change(int &x,int h,int t,int pos,int k)
{
if (!x) x=++cnt;
if (h==t)
{
v[x]+=k; p[x]=pos; return;
}
if (pos<=mid) change(ls[x],h,mid,pos,k);
else change(rs[x],mid+,t,pos,k);
updata(x);
}
int merge(int x,int y,int h,int t)
{
if (!x||!y) return(x^y);
ls[x]=merge(ls[x],ls[y],h,mid);
rs[x]=merge(rs[x],rs[y],mid+,t);
if (h==t) v[x]+=v[y];
else updata(x);
return(x);
}
}se1;
void dfs2(int x)
{
rint u=head[x];
while (u)
{
rint v=a[u].b;
if(v!=fa[x])
{
dfs2(v);
root[x]=se1.merge(root[x],root[v],,m);
}
u=a[u].a;
}
for (rint i=;i<ve1[x].size();i++)
se1.change(root[x],,m,ve1[x][i],);
for (rint i=;i<ve2[x].size();i++)
se1.change(root[x],,m,ve2[x][i],-);
if(!se1.v[root[x]]) ans[x]=;
else ans[x]=se1.p[root[x]];
}
IL bool cmp(re x,re y)
{
return(x.a<y.a);
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(n); read(m);
int x,y;
for (int i=;i<=n-;i++)
{
read(x); read(y); arr(x,y); arr(y,x);
}
dfs();
for (rint i=;i<=;i++)
for (rint j=;j<=cnt2;j++)
if ((<<(i-))+j-<=cnt2)
bz[i][j]=min(bz[i-][j],bz[i-][j+(<<(i-))]);
for( int i=;i<=m;i++)
{
read(c[i].a); read(c[i].b);
read(b[i].a); b[i].b=i;
}
sort(b+,b+m+,cmp);
b[].a=1e9;
int cnt3=;
for (int i=;i<=m;i++)
{
if (b[i].a!=b[i-].a)
{
cnt3++;
fdy[cnt3]=b[i].a;
}
vt[b[i].b]=cnt3;
}
for (int i=;i<=m;i++)
{
int x=c[i].a,y=c[i].b,z=vt[i];
// cout<<x<<" "<<y<<" "<<z<<" ";
int xx=lca(x,y);
//cout<<xx<<endl;
ve1[x].push_back(z);
ve1[y].push_back(z);
ve2[xx].push_back(z);
ve2[fa[xx]].push_back(z);
}
dfs2();
for (int i=;i<=n;i++)
{
printf("%d\n",fdy[ans[i]]);
}
return ;
}
//离散化

拍:

#include <bits/stdc++.h>
using namespace std;
const int N=1e3;
int v[N][N];
int head[N],n,m,l;
struct re{
int a,b;
}a[N*];
void arr(int x,int y)
{
a[++l].a=head[x];
a[l].b=y;
head[x]=l;
}
int cnt=,id[N],dy[N],fa[N];
void dfs(int x,int fa1)
{
int u=head[x];
id[x]=++cnt;
dy[cnt]=x;
while (u)
{
int v=a[u].b;
if (v!=fa1) fa[v]=x,dfs(v,x);
u=a[u].a;
}
}
const int INF=1e9;
bool pd(int x,int y)
{
while (x!=y&&x) x=fa[x];
if(x==y) return(); else return();
}
int lca(int x,int y)
{
int ans=;
for (int i=;i<=n;i++)
if (pd(x,i)&&pd(y,i)) ans=max(ans,id[i]);
return(dy[ans]);
}
int main()
{
freopen("1.in","r",stdin);
freopen("2.out","w",stdout);
cin>>n>>m;
for (int i=;i<=n-;i++)
{
int x,y;
cin>>x>>y;
arr(x,y); arr(y,x);
}
dfs(,);
for (int i=;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
int xx=lca(x,y);
for (int i=x;i!=fa[xx];i=fa[i]) v[i][z]++;
for (int i=y;i!=fa[xx];i=fa[i]) v[i][z]++;
v[xx][z]--;
}
for (int i=;i<=n;i++)
{
int ans=,ans2=;
for (int j=;j<=;j++)
if(v[i][j]>ans) ans=v[i][j],ans2=j;
cout<<ans2<<endl;
}
return ;
}

数据:

#include <bits/stdc++.h>
using namespace std;
int main()
{
freopen("1.in","w",stdout);
int n=,m=;
cout<<n<<" "<<m<<endl;
srand(time());
for (int i=;i<=n;i++)
{
int x=rand()%(i-)+;
cout<<x<<" "<<i<<endl;
}
for (int i=;i<=m;i++)
{
int x=rand()%n+,y=rand()%n+,z=rand()%+;
cout<<x<<" "<<y<<" "<<z<<endl;
}
}

【BZOJ3307】雨天的尾巴的更多相关文章

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

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

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

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

  3. BZOJ3307 雨天的尾巴

    首先考虑序列怎么做... 只要把操作差分了,记录在每个点上 然后维护一棵权值线段树,表示每个颜色出现的次数,支持单点修改和查询最大值操作 只要把序列扫一遍就好了,时间复杂度$O(n + m*logZ) ...

  4. BZOJ3307雨天的尾巴——线段树合并

    题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来N ...

  5. [洛谷P4556][BZOJ3307]雨天的尾巴-T3订正

    线段树合并+树上差分 题目链接(···) 「简单」「一般」——其实「一般」也只多一个离散化 考试时想法看>这里< 总思路:先存所有的操作,离散化,然后用树上差分解决修改,用权值线段树维护每 ...

  6. [BZOJ3307]:雨天的尾巴(LCA+树上差分+权值线段树)

    题目传送门 题目描述: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式: 第一 ...

  7. bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)

    Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后,每个点存放最多的是哪种物品. Input ...

  8. bzoj3307雨天的尾巴(权值线段树合并/DSU on tree)

    题目大意: 一颗树,想要在树链上添加同一物品,问最后每个点上哪个物品最多. 解题思路: 1.线段树合并 假如说物品数量少到可以暴力添加,且树点极少,我们怎么做. 首先在一个树节点上标记出哪些物品有多少 ...

  9. bzoj3307 雨天的尾巴题解及改题过程(线段树合并+lca+树上差分)

    题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式 第一行数字N,M接下 ...

  10. [BZOJ3307] 雨天的尾巴-----------------线段树进阶

    虽然是个板子,但用到了差分思想. Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最 ...

随机推荐

  1. Jena搭建SPARQL查询RDF数据

    1 Jena搭建SPARQL查询RDF数据 1.1 Jena概要 · SPARQL是W3C的RDF数据工作组设计的一种查询语言和协议,用于RDF数据的查询.经过类似于JDK安装时候的配置,可以在命令行 ...

  2. HashMap分析及散列的冲突处理

    1,Hashing过程 像二分查找.AVL树查找,这些查找算法的时间复杂度为O(logn),而对于哈希表而言,我们一般说它的查找时间复杂度为O(1).那它是怎么实现的呢?这就是一个Hashing过程. ...

  3. JAVA 并发编程学习(2)之基本概念

    1,是不是线程创建越多越好? 当一个程序创建了大量的线程时,活跃的线程会消耗内存.若可运行的线程数量多于可用处理器的数量,那么有些线程将闲置.大量空闲的线程会占用许多内存,给垃圾回收带来压力,而且大量 ...

  4. TestNg失败重试机制

    TestNg提供了失败重试接口IRetryAnalyzer,需要实现retry方法: package com.shunhe.testngprac.retry; import org.testng.IR ...

  5. 使用PLC作为payload/shellcode分发系统

    这个周末,我一直在鼓捣Modbus,并利用汇编语言开发了一个stager,它可以从PLC的保持寄存器中下载payload.由于有大量的PLC都暴露在互联网上,我情不自禁地想到,是否可以利用它们提供的处 ...

  6. Python实现Plugin

    1. Plugin与Python 插件的历史最早可追溯至1970年代,它是一种程序组件,通过和应用程序的互动,为应用程序增加一些所需要的特定的功能[维基].插件允许第三方开发者对已有的程序功能进行扩展 ...

  7. 串行动画组QSequentialAnimationGroup

    按顺序执行动画 该类就是用来按照动画添加顺序来执行动画的.我们只用实例化该类,然后通过调用addAnimation()或者insertAnimation()方法把各个动画添加进去就可以了 import ...

  8. 【洛谷P2704【NOI2001】】炮兵阵地

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

  9. mysql 案例 ~ pt修复工具的使用

    简介:今天咱们来聊聊PT修复工具pt-table-sync 注意事项:   1 表要有主键或者唯一键   2 针对每一个chunk加的是for update锁   3 修复过程中不能容忍从库延迟 如果 ...

  10. 【学习博客】Python学习初体验

    本周是正式开始学习Python的第一周.很久不写代码了,毕业第5年了,期间几乎没怎么动过手.这段时间比较规律.密集的学习又让我找回了当时的感觉,还不算陌生,我挺喜欢的这种能实实在在看到自己知识增长的状 ...