并不对劲的bzoj4538:loj2049:p3250:[HNOI2016]网络
题意
有一棵\(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]网络的更多相关文章
- P3250 [HNOI2016]网络
LINK:网络 一棵树 每次添加一条路径 或者删除之前的一条路径 或询问除了不经过某个点之外剩下的最大值. 一个显然的思路 对于一条路径的权值我们直接把权值塞上去 标记永久化一下即可. 考虑如何求答案 ...
- luogu P3250 [HNOI2016]网络
传送门 考虑只有一个询问,怎么使用暴力枚举最快的得到答案.因为要求最大的,所以可以把链按权值从大往小排序,然后往后扫,找到一个没有交的就是答案,直接退出 一堆询问,可以考虑整体二分,先二分一个值\(m ...
- 洛咕P3250 [HNOI2016]网络 整体二分
这题太神仙了必须写博客... 显然可以想到二分答案.二分一个答案mid,如果所有长度\(\geq mid\)的路径都过x,那么答案一定\(<mid\),否则答案\(\geq mid\). 那么就 ...
- [洛谷P3250][HNOI2016]网络
题目大意:给定一棵树.有三种操作: $0\;u\;v\;t:$在$u$到$v$的链上进行重要度为$t$的数据传输. $1\;x:$结束第$x$个数据传输. $2\;x:$询问不经过点$x$的数据传输中 ...
- 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)
传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...
- P3250 [HNOI2016] 网络 (树剖+堆/整体二分+树上差分+树状数组)
解法1: 本题有插入路径和删除路径,在每个节点维护插入堆和删除堆,查询时两者top一样则一直弹出.如果每个节点维护的是经过他的路径,显然有些不好处理,正难则反,每个点维护不经过他的路径,那么x节点出了 ...
- 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组
[BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...
- BZOJ 4538: [Hnoi2016]网络 [整体二分]
4538: [Hnoi2016]网络 题意:一棵树,支持添加一条u到v权值为k的路径,删除之前的一条路径,询问不经过点x的路径的最大权值 考虑二分 整体二分最大权值,如果\(k \in [mid+1, ...
- 【LG3250】[HNOI2016]网络
[LG3250][HNOI2016]网络 题面 洛谷 题解 30pts 对于\(m\leq 2000\),直接判断一下这个个点是否断掉一个交互,没断掉的里面取\(max\)即可,复杂度\(O(m^2\ ...
随机推荐
- js毫秒数转换为具体日期
[1].毫秒数转换为具体日期 function getMyDate(str) { var oDate = new Date(str), oYear = oDate.getFullYear( ...
- 优化webpack打包速度方案
基本原理要么不进行打包:要么缓存文件,不进行打包:要么加快打包速度. 不进行打包方案: 1,能够用CDN处理的用CDN处理,比如项目引入的第三方依赖jquery.js,百度编辑器 先进行打包或者缓存然 ...
- YOLO: You Only Look Once论文阅读摘要
论文链接: https://arxiv.org/pdf/1506.02640.pdf 代码下载: https://github.com/gliese581gg/YOLO_tensorflow Abst ...
- CentOS7 源码安装 PostgreSQL 12
PostgreSQL 12 源码安装 Table of Contents 1. 下载 2. 准备环境 3. 编译安装 4. 设置环境变量 5. 初始化数据库 6. 配置参数文件 6.1. postgr ...
- MybatisUtil工具类的作用
1)在静态初始化块中加载mybatis配置文件和StudentMapper.xml文件一次 2)使用ThreadLocal对象让当前线程与SqlSession对象绑定在一起 3)获取当前线程中的Sql ...
- MySQL主从双向同步
最近部署测试环境,涉及到MySQL数据库主从双向同步的部署,记录一下部署过程,正常读写都发生在主库,从库作为备选数据库(热备份),当主库发生异常,数据库自动切换到从库,这里面是怎么监控数据库异常并触发 ...
- 纯CSS实现加载转圈样式
不同的项目中对于等待加载时转圈圈的样式是不同的,有的是传统的转圈的gif图片,见得比较多的是将转圈圈的换成了可爱的图标.有时候项目中加入等待加载的图片会很违和,不符合美观,所以需要用CSS做一个.下面 ...
- 来自iSpy整理的最全海康大华IPC的RTSP连接地址
来自iSpy整理的最全海康大华IPC的RTSP连接地址 先贴出处: 海康:http://www.ispyconnect.com/man.aspx?n=Hikvision 大华:http://www.i ...
- docker-搭建efk收集docker日志
新建docker-compose.yml文件 version: '2' services: fluentd: build: ./fluentd volumes: - ./fluentd/conf:/f ...
- js有序数组中插入一个元素,并有序的输出
题目:比较传入函数的参数,将参数组成数组,从小到大排序,返回新的数组. 如: insert();console.log(arr); //[] insert(-1,-2); console.log(ar ...