【BZOJ3307】雨天的尾巴
题解:
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】雨天的尾巴的更多相关文章
- [BZOJ3307] 雨天的尾巴(树上差分+线段树合并)
[BZOJ3307] 雨天的尾巴(树上差分+线段树合并) 题面 给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型. N, M≤100000 分析 ...
- [bzoj3307]雨天的尾巴_线段树合并
雨天的尾巴 bzoj-3307 题目大意:N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. ...
- BZOJ3307 雨天的尾巴
首先考虑序列怎么做... 只要把操作差分了,记录在每个点上 然后维护一棵权值线段树,表示每个颜色出现的次数,支持单点修改和查询最大值操作 只要把序列扫一遍就好了,时间复杂度$O(n + m*logZ) ...
- BZOJ3307雨天的尾巴——线段树合并
题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来N ...
- [洛谷P4556][BZOJ3307]雨天的尾巴-T3订正
线段树合并+树上差分 题目链接(···) 「简单」「一般」——其实「一般」也只多一个离散化 考试时想法看>这里< 总思路:先存所有的操作,离散化,然后用树上差分解决修改,用权值线段树维护每 ...
- [BZOJ3307]:雨天的尾巴(LCA+树上差分+权值线段树)
题目传送门 题目描述: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式: 第一 ...
- bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)
Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后,每个点存放最多的是哪种物品. Input ...
- bzoj3307雨天的尾巴(权值线段树合并/DSU on tree)
题目大意: 一颗树,想要在树链上添加同一物品,问最后每个点上哪个物品最多. 解题思路: 1.线段树合并 假如说物品数量少到可以暴力添加,且树点极少,我们怎么做. 首先在一个树节点上标记出哪些物品有多少 ...
- bzoj3307 雨天的尾巴题解及改题过程(线段树合并+lca+树上差分)
题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式 第一行数字N,M接下 ...
- [BZOJ3307] 雨天的尾巴-----------------线段树进阶
虽然是个板子,但用到了差分思想. Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最 ...
随机推荐
- 《Maven实战》笔记
maven是什么 maven是 构建工具 依赖关系工具 项目信息管理工具 而JAVA世界的ant只是一个构建工具,不具备依赖管理的功能,需要配合使用ivy进行依赖管理. maven的安装 下载mave ...
- 去除inline-block出现间距的几种方法
display:inline-block,简单来说就是将对象呈现为inline对象,但是对象的内容作为block对象呈现,之后的内联对象会排列在同一行 比如两个input,默认中间会产生一些间距 &l ...
- Prometheus 监控 Nginx 流量 (三)
介绍 基于Openresty和Prometheus.Consul.Grafana设计的,实现了针对域名和Endpoint级别的流量统计,使用Consul做服务发现.KV存储,Grafana做性能图展示 ...
- include的作用
#include发生在预处理阶段,整个编译链接过程,#include是最简单的了,没有之一.就是在include的位置直接把文件原原本本完完整整一字不落的包含进来,下面举一个极端点的例子: //fil ...
- js中,for循环里面放ajax,ajax访问不到变量以及每次循环获取不到数据问题总结
想在点击"终端控制"的时候能够开启多个窗口对多个终端进行管理: /**提交事件**/ $("#terminalControl").bind("clic ...
- springboot学习笔记-6 springboot整合RabbitMQ
一 RabbitMQ的介绍 RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿 ...
- 记一次Win Server 2012部署问题及解决方法
1.前言 本章内容为在win server 2012服务器部署时遇到的问题及解决方法.大致工作为:两台服务器,一台web.一台数据库:web服务器部署.net web程序,数据库服务器安装oracle ...
- 【vim】实时计算器
在插入模式下,你可以使用 Ctrl+r 键然后输入 =,再输入一个简单的算式.按 Enter 键,计算结果就会插入到文件中.例如,尝试输入: Ctrl+r '=2+2' ENTER 然后计算结果&qu ...
- shiro设置session超时时间
系统默认超时时间是180000毫秒(30分钟) long timeout = SecurityUtils.getSubject().getSession().getTimeout(); System. ...
- C/C++杂记:虚函数的实现的基本原理
1. 概述 简单地说,每一个含有虚函数(无论是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针.例: 其中: B的虚函数表中存放着B::foo和B ...