题意

有一棵\(n\)(\(n\leq 10^5\))个点的树,\(m\)(\(m\leq 2\times 10^5\))个操作。操作有三种:1.给出\(u,v,k\),表示加入一条从\(u\)到\(v\)权值为\(k\)的路径;2.给出\(k\),表示删除\(k\)时刻加入的路径;3.给出\(x\),表示询问不经过点\(x\)的路径的权值最大值。

题解

3操作看上去很奇怪,先假装它是“询问经过\(x\)的路径的权值最大值”。

这样1操作就可以看成区间修改为最大值,3操作可以看成单点求值。注意这是不用pushdown的,因为线段树中一个点的值应该是所有祖先的tag的最大值。

2操作是区间删一个数,那么可以在线段树的每个点维护一个可删堆,1操作变成向一个区间的点的堆中加一个数,2操作变成将一个区间的点的堆删一个数。

这样之所以是对的,是因为没有pushdown或pushup,使1操作时涉及的区间和对应的2操作涉及的区间是相同的,不会有堆被删空。

再考虑3操作。

这时1、2操作影响的区域就由“这条路径上的点”变成了“不在这条路径上的点”,需要手动处理出 在这条路径上的点的区间 的补集。

注意不能先将区间\([1,n]\)区间加数再将这条路径上的点的区间删数,因为“将区间\([1,n]\)区间加数”只会改线段树根节点的堆,而“将这条路径上的点的区间删数”会把某些点的堆大小删成负数。

代码

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 100007
#define maxm 200007
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>
#define ls (u<<1)
#define rs (u<<1|1)
#define mi ((l+r)>>1)
#define fi first
#define se second
#define mp make_pair
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
char ch[20];int f=0;
if(!x){putchar('0'),putchar('\n');return;}
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
}
struct deadque
{
priority_queue<int>yes,no;
int top(){while(!no.empty()&&yes.top()==no.top())yes.pop(),no.pop();return yes.top();}
int size(){return yes.size()-no.size();}
void push(int x){return yes.push(x);}
void del(int x){return no.push(x);}
}q[maxn<<2];
int fir[maxn],nxt[maxm],v[maxm],cnte,qa[maxm],qb[maxm],qc[maxm];
int n,m,dep[maxn],son[maxn],fa[maxn],top[maxn],siz[maxn],dfn[maxn],tim,num;
pii b[maxn];
void ade(int u1,int v1){v[cnte]=v1,nxt[cnte]=fir[u1],fir[u1]=cnte++;}
void getson(int u)
{
siz[u]=1;
view(u,k)if(v[k]!=fa[u])
{
fa[v[k]]=u,dep[v[k]]=dep[u]+1,getson(v[k]),siz[u]+=siz[v[k]];
if(!son[u]||siz[son[u]]<siz[v[k]])son[u]=v[k];
}
}
void gettop(int u,int anc)
{
dfn[u]=++tim,top[u]=anc;
if(son[u])gettop(son[u],anc);
view(u,k)if(v[k]!=fa[u]&&v[k]!=son[u])gettop(v[k],v[k]);
}
void add(int u,int l,int r,int x,int y,int k,int f)
{
if(x<=l&&r<=y){if(f)q[u].push(k);else q[u].del(k);return;}
if(x<=mi)add(ls,l,mi,x,y,k,f);
if(y>mi)add(rs,mi+1,r,x,y,k,f);
}
int ask(int u,int l,int r,int x)
{
if(x<=l&&r<=x){return q[u].size()==0?-1:q[u].top();}
int res=q[u].size()==0?-1:q[u].top();
if(x<=mi)return max(res,ask(ls,l,mi,x));
return max(res,ask(rs,mi+1,r,x));
}
void addrd(int x,int y,int k,int f)
{
num=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
num++,b[num]=mp(dfn[top[x]],dfn[x]),x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
num++,b[num]=mp(dfn[y],dfn[x]);
int lst=1;
sort(b+1,b+num+1);
rep(i,1,num)
{
if(lst<=b[i].fi-1)add(1,1,n,lst,b[i].fi-1,k,f);
lst=b[i].se+1;
}
if(lst<=n)add(1,1,n,lst,n,k,f);
}
int main()
{
memset(fir,-1,sizeof(fir));
n=read(),m=read();
rep(i,1,n-1){int x=read(),y=read();ade(x,y),ade(y,x);}
getson(1),gettop(1,1);
rep(i,1,m)
{
int t=read();
if(t==0){qa[i]=read(),qb[i]=read(),qc[i]=read();addrd(qa[i],qb[i],qc[i],1);}
else if(t==1){int j=read();if(qa[j]==0)continue;addrd(qa[j],qb[j],qc[j],0);}
else{int x=read();write(ask(1,1,n,dfn[x]));}
}
return (0-0);
}

并不对劲的bzoj4538:loj2049:p3250:[HNOI2016]网络的更多相关文章

  1. P3250 [HNOI2016]网络

    LINK:网络 一棵树 每次添加一条路径 或者删除之前的一条路径 或询问除了不经过某个点之外剩下的最大值. 一个显然的思路 对于一条路径的权值我们直接把权值塞上去 标记永久化一下即可. 考虑如何求答案 ...

  2. luogu P3250 [HNOI2016]网络

    传送门 考虑只有一个询问,怎么使用暴力枚举最快的得到答案.因为要求最大的,所以可以把链按权值从大往小排序,然后往后扫,找到一个没有交的就是答案,直接退出 一堆询问,可以考虑整体二分,先二分一个值\(m ...

  3. 洛咕P3250 [HNOI2016]网络 整体二分

    这题太神仙了必须写博客... 显然可以想到二分答案.二分一个答案mid,如果所有长度\(\geq mid\)的路径都过x,那么答案一定\(<mid\),否则答案\(\geq mid\). 那么就 ...

  4. [洛谷P3250][HNOI2016]网络

    题目大意:给定一棵树.有三种操作: $0\;u\;v\;t:$在$u$到$v$的链上进行重要度为$t$的数据传输. $1\;x:$结束第$x$个数据传输. $2\;x:$询问不经过点$x$的数据传输中 ...

  5. 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)

    传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...

  6. P3250 [HNOI2016] 网络 (树剖+堆/整体二分+树上差分+树状数组)

    解法1: 本题有插入路径和删除路径,在每个节点维护插入堆和删除堆,查询时两者top一样则一直弹出.如果每个节点维护的是经过他的路径,显然有些不好处理,正难则反,每个点维护不经过他的路径,那么x节点出了 ...

  7. 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组

    [BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...

  8. BZOJ 4538: [Hnoi2016]网络 [整体二分]

    4538: [Hnoi2016]网络 题意:一棵树,支持添加一条u到v权值为k的路径,删除之前的一条路径,询问不经过点x的路径的最大权值 考虑二分 整体二分最大权值,如果\(k \in [mid+1, ...

  9. 【LG3250】[HNOI2016]网络

    [LG3250][HNOI2016]网络 题面 洛谷 题解 30pts 对于\(m\leq 2000\),直接判断一下这个个点是否断掉一个交互,没断掉的里面取\(max\)即可,复杂度\(O(m^2\ ...

随机推荐

  1. js毫秒数转换为具体日期

    [1].毫秒数转换为具体日期 function getMyDate(str) {    var oDate = new Date(str),    oYear = oDate.getFullYear( ...

  2. 优化webpack打包速度方案

    基本原理要么不进行打包:要么缓存文件,不进行打包:要么加快打包速度. 不进行打包方案: 1,能够用CDN处理的用CDN处理,比如项目引入的第三方依赖jquery.js,百度编辑器 先进行打包或者缓存然 ...

  3. YOLO: You Only Look Once论文阅读摘要

    论文链接: https://arxiv.org/pdf/1506.02640.pdf 代码下载: https://github.com/gliese581gg/YOLO_tensorflow Abst ...

  4. CentOS7 源码安装 PostgreSQL 12

    PostgreSQL 12 源码安装 Table of Contents 1. 下载 2. 准备环境 3. 编译安装 4. 设置环境变量 5. 初始化数据库 6. 配置参数文件 6.1. postgr ...

  5. MybatisUtil工具类的作用

    1)在静态初始化块中加载mybatis配置文件和StudentMapper.xml文件一次 2)使用ThreadLocal对象让当前线程与SqlSession对象绑定在一起 3)获取当前线程中的Sql ...

  6. MySQL主从双向同步

    最近部署测试环境,涉及到MySQL数据库主从双向同步的部署,记录一下部署过程,正常读写都发生在主库,从库作为备选数据库(热备份),当主库发生异常,数据库自动切换到从库,这里面是怎么监控数据库异常并触发 ...

  7. 纯CSS实现加载转圈样式

    不同的项目中对于等待加载时转圈圈的样式是不同的,有的是传统的转圈的gif图片,见得比较多的是将转圈圈的换成了可爱的图标.有时候项目中加入等待加载的图片会很违和,不符合美观,所以需要用CSS做一个.下面 ...

  8. 来自iSpy整理的最全海康大华IPC的RTSP连接地址

    来自iSpy整理的最全海康大华IPC的RTSP连接地址 先贴出处: 海康:http://www.ispyconnect.com/man.aspx?n=Hikvision 大华:http://www.i ...

  9. docker-搭建efk收集docker日志

    新建docker-compose.yml文件 version: '2' services: fluentd: build: ./fluentd volumes: - ./fluentd/conf:/f ...

  10. js有序数组中插入一个元素,并有序的输出

    题目:比较传入函数的参数,将参数组成数组,从小到大排序,返回新的数组. 如: insert();console.log(arr); //[] insert(-1,-2); console.log(ar ...