题意:给你一棵n个点的树。m个操作,op 1:在点i上建立银行。op 2:询问从点x开始可以经过至少一个银行走到的点中编号第二大的点。

n,m<=1e5.

标程:

 #include<bits/stdc++.h>
using namespace std;
int read()
{
int x=;char ch=getchar();
while (ch<''||ch>'') ch=getchar();
while (''<=ch&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x;
}
const int N=;
set<int,greater<int> > s;
set<int,greater<int> >::iterator it;
int cnt,head[N],Mx[N],Mxc[N],f[N],tot,ans[N],tag[N],u,v,n,m;
struct node{int to,next;}num[N*];
struct _node{int op,x;}q[N];
void add(int x,int y)
{num[++cnt].to=y;num[cnt].next=head[x];head[x]=cnt;}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void merge(int x,int y)
{
if (x==y) return;
s.erase(Mx[x]);s.erase(Mx[y]);
s.erase(Mxc[x]);s.erase(Mxc[y]);
if (Mx[x]>Mx[y]) Mxc[y]=Mx[y],Mx[y]=Mx[x];//注意最大次大的传递
else if (Mx[x]>Mxc[y]) Mxc[y]=Mx[x];
if (Mxc[x]>Mxc[y]) Mxc[y]=Mxc[x];
s.insert(Mx[y]);s.insert(Mxc[y]);
f[x]=y;
}
void dfs(int x,int fa)
{
if (tag[x]) s.insert(x);//银行作为单点也要加入
for (int i=head[x];i;i=num[i].next)
if (num[i].to!=fa)
{
dfs(num[i].to,x);
if (!tag[num[i].to]&&!tag[x]) merge(find(num[i].to),find(x));
}
}
int qry(int x)
{
int fl=;x=find(x);
for (it=s.begin();it!=s.end();++it)
{
if (*it==Mx[x]||*it==Mxc[x]) continue;
if (!fl) fl=;else return *it;
}
return -;
}
int main()
{
n=read();m=read();tot=;s.clear();
memset(head,,sizeof(head));cnt=;
for (int i=;i<n;i++) u=read(),v=read(),add(v,u),add(u,v);
for (int i=;i<=n;i++) f[i]=i,Mx[i]=i,Mxc[i]=,s.insert(i);
for (int i=;i<=m;i++)
{
q[i].op=read(),q[i].x=read();
if (q[i].op==) tag[q[i].x]++;//有可能被该银行被统计多次
}
dfs(,-);
for (int i=m;i>=;i--)
{
if (q[i].op==)
{
int now=find(q[i].x);tag[q[i].x]--;
if (!tag[q[i].x])
for (int j=head[q[i].x];j;j=num[j].next)
if (!tag[num[j].to]) merge(find(num[j].to),now);
}else ans[++tot]=qry(q[i].x);
}
while (tot) printf("%d\n",ans[tot--]);
return ;
}

题解:并查集+技巧

暴力可以过很多啊,倒着枚举编号点,判断x和该编号点的路径上是否有银行,树链剖分+线段树(lct)维护即可。

因为连通块拆分比较麻烦,考虑倒着执行操作,相当于删去银行。每删去一个银行就相当于把若干个连通块合并。

询问即是问除了x点所在连通块其他部分的第二大。维护一个保存每个连通块最大次大的set,取出不等于当前连通块最大次大的第二大元素,最多取4次即可。

时间复杂度O((n+m)(logn+a(n))。

最新文章

  1. [Erlang 0110] Erlang Abstract Format , Part 1
  2. Java分页需求
  3. 20161106PM-接口
  4. 单机搭建Android开发环境(三)
  5. linux-ubuntu常用命令
  6. c#游戏 剪刀石头
  7. ios基础篇(四)——UILabel的常用属性及方法
  8. 【转】Android中visibility属性VISIBLE、INVISIBLE、GONE的区别
  9. MyBatis报错
  10. IDEA 快捷键整理
  11. php 随笔
  12. [转]Java7中的ForkJoin并发框架初探(下)—— ForkJoin的应用
  13. [ExtJS5学习笔记]第二十一节 Extjs5中使用config配置给ext.widget或者create方法传递参数
  14. Tom DeMarco:软件工程这个概念已过时?
  15. MyEclipse破解步骤
  16. itext7知识点研究(PDF编辑)
  17. A. 【UNR #2】积劳成疾
  18. POJ-1456 Supermarket 销售商品【贪心】+【并查集】
  19. 解决IIS7虚拟目录出现HTTP 错误 500.19(由于权限不足而无法读取配置文件)的问题
  20. 关于vue的npm run dev和npm run build

热门文章

  1. hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机
  2. django中filter()和get()的区别
  3. 6、 restful API
  4. jquery操作html元素之(设置内容和属性)
  5. linux最常用vim命令记录
  6. 当class有多个class属性时截取操作
  7. 关于合并pdf文件出现的问题
  8. Spring MVC @PathVariable注解(3)
  9. BBS论坛 注册功能
  10. C#让两个长度相同的数组一一对应