【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类型的物品.完成所有发放后,每个点存放最 ...
随机推荐
- Linux 命令详解(九)轻易删除OpenSSL 的后果
警告自己,不要轻易的去删除系统的软件 1.composer自动更新出现错误 www@TinywanAliYun:~/web/go-study-line$ composer self-update Ke ...
- java抽象类与接口回顾
1.抽象类中可以包括成员变量,方法,构造器,初始化块,内部类(接口/枚举)五种成分.2.让A类中包含B方法,又不提供B方法的实现,即抽象方法只有方法签名,没有方法体.3.有抽象方法的类只能被定义成抽象 ...
- modbus-vcr介绍
相关链接:modbus-vcr modbus-vcr是一个Ettercap的插件,被使用在缺少数据完整性的工业控制系统协议方面. 这个Ettercap插件执行一个MITM攻击在使用Modbus协议的系 ...
- jquery 学习(二) - 属性操作
html代码 <div class="n1" zdy="z1">AAA <p>1111111</p> <input t ...
- 用代码生成UINavigationController 与UITabBarController相结合的简单QQ框架(部分)
首先我们需要搭建一个空的项目,当然xcode6.0以后不支持直接创建空项目,所以我们需要在系统生成项目之后,删除xcode自动给你生成的控制器和storyboard,另外需要在Main Interfa ...
- SSH开发环境搭建
断断续续学习hibernate也有一段时间了,在这里研究一下SSH开发环境的搭建过程,自己简单的搭建一个SSH的开发环境.采用maven搭建. 0.项目结构: 1.导包:(maven项目) pom.x ...
- oracle新建对象 权限管理
代码 CREATE USER target IDENTIFIED BY target ; GRANT CONNECT, RESOURCE TO target; 刚刚创建的oracle实例中会内建两个用 ...
- Modelsim SE 安装
FPGA开发过程中,代码编写完成后,往往是需要通过第三方仿真工具去验证设计功能的正确性.本章介绍最常用的仿真工具--Modelsim SE的安装过程. 1.1.1.Modelsim SE安装 本节主要 ...
- Python startswith() 函数 判断字符串开头
Python startswith() 函数 判断字符串开头 函数:startswith() 作用:判断字符串是否以指定字符或子字符串开头 一.函数说明语法:string.startswith(str ...
- WPF中添加Winform用户自定义控件
过程:创建WPF工程->创建Winform用户自定义控件工程->WPF中引用控件->添加到Xaml页面 1.首先在WPF工程的解决方案上右击选择添加新建项目: 选择Windows窗体 ...