【bzoj 4046 加强版】Pork barrel
刚考完以为是神仙题……后来发现好像挺蠢的…… QwQ
题意
给你一张 \(n\) 个点 \(m\) 条边的无向图(不一定连通),有 \(q\) 组询问,每组询问给你 \(2\) 个正整数 \(l,h\),你需要选出一些边,满足边权都在 \([l,h]\) 范围内,连通尽量多的点对,在此基础上使得边权和最小。
\(1\le n,m,q\le 10^5,\space 1\le w_i,l,h\le 10^4\)(原题 \(n\le 1000,\space q\le 10^6\))
题解
动态最小生成树(汗)
我怎么什么都没写过
考场上花 10 分钟写了 5 分 \(O(qn)\) 暴力就滚了
假设这题可以离线,先将所有边按权值从大到小排序。
依次判断每条边的两端点是否连通,若未连通则连上(这样连通的点对数必定增多),若连通则替换掉一条树上这两点之间的简单路径上 权值最大的一条边(\(\text{cut}\) 一下权值最大的那条边,\(\text{link}\) 一下这条边)。
加边的同时动态处理询问。对于一组询问 \([L,R]\),若当前插入的边的权值是 \(\ge L\) 的最小值,则我们决定处理这组询问。此时最小生成(森林)上的所有边权都 \(\ge L\),我们直接扔掉所有权值 \(\gt R\) 的边,剩余的边的权值和就是答案。发现边权很小,所以可以用树状数组动态维护最小生成(森林)中的边权,第 \(i\) 位记录所有权值为 \(i\) 的边的权值和,单点修改,区间查询。
考虑在线,我想这题时居然忘了加边和询问是分开的了……
依然把边按权值从大到小排序,每加入一条边时,第 \(i\) 个版本继承第 \(i+1\) 个版本,在主席树的第 \(w_i\) 个版本上单点修改即可。在线处理询问 \([L,R]\) 时在主席树的第 \(L\) 个版本上区间查询即可。
复杂度 \(O(n\log n)\)。
仔细想想好像确实挺水的,所以还是我太菜了
附注:
1. \(LCT\) 一般维护点权,边权不太好维护,可以把第 \(i\) 条边转成一个编号为 \(i+n\) 的点,然后加入这条边的时候 把这个点与边的两端点 \(\text{link}\) 一下即可
2. 注意主席树的空间是 \(O(2m\log w)\) 的!!!不是 \(O(10000\log 10000)\)!!!因为这个 sb 问题调了一小时 zbl
#include<bits/stdc++.h>
#define N 200010
using namespace std;
inline int read(){
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
if(f) return x; return 0-x;
}
int n,m,online,q;
struct inp{int u,v,w;}a[N<<1];
inline bool cmp(inp a, inp b){
return a.w>b.w;
}
namespace LCT{
#define son(x,fx) tr[x].son[fx]
struct Tree{int fa,son[2],v,mx_id; bool r;}tr[N<<1];
inline bool isRoot(int x){
return son(tr[x].fa,0)!=x && son(tr[x].fa,1)!=x;
}
inline bool idf(int x){
return son(tr[x].fa,1)==x;
}
void pushup(int x){
tr[x].mx_id=x;
if(tr[tr[son(x,0)].mx_id].v > tr[tr[x].mx_id].v) tr[x].mx_id=tr[son(x,0)].mx_id;
if(tr[tr[son(x,1)].mx_id].v > tr[tr[x].mx_id].v) tr[x].mx_id=tr[son(x,1)].mx_id;
}
void pushdown(int x){
if(tr[x].r){
swap(son(x,0),son(x,1));
tr[son(x,0)].r^=1, tr[son(x,1)].r^=1;
tr[x].r=0;
}
}
void pd(int x){
if(!isRoot(x)) pd(tr[x].fa);
pushdown(x);
}
inline void connect(int x, int f, int fx){
tr[x].fa=f, son(f,fx)=x;
}
void rotate(int x){
int y=tr[x].fa, z=tr[y].fa, idf_x=idf(x), idf_y=idf(y), B=son(x,idf_x^1);
if(!isRoot(y)) connect(x,z,idf_y);
else tr[x].fa=z;
connect(B,y,idf_x), connect(y,x,idf_x^1);
pushup(y), pushup(x);
}
void splay(int x){
pd(x);
int f;
for(; !isRoot(x); ){
f=tr[x].fa;
if(!isRoot(f)) rotate(idf(x)==idf(f) ? f : x);
rotate(x);
}
}
void access(int x){
for(int y=0; x; x=tr[y=x].fa){
splay(x);
son(x,1)=y;
pushup(x);
}
}
void makeroot(int x){
access(x), splay(x), tr[x].r^=1;
}
void link(int x, int y){
makeroot(x);
tr[x].fa=y;
}
int cutMax(int x, int y){
makeroot(x);
access(y);
splay(y);
x=tr[y].mx_id;
splay(x);
tr[son(x,0)].fa=tr[son(x,1)].fa=0;
son(x,0)=son(x,1)=0;
return x;
}
#undef son
}using namespace LCT;
namespace PT{
#define son(x,fx) tr[o].son[fx]
int cnt,rt[100010];
struct Tree{int son[2],sum;}tr[200010*20];
void ins(int &o, int pre, int l, int r, int x, int v){
tr[o=++cnt] = tr[pre], tr[o].sum += v;
if(l==r) return;
int mid=l+r>>1;
if(x<=mid) ins(son(o,0),son(pre,0),l,mid,x,v);
else ins(son(o,1),son(pre,1),mid+1,r,x,v);
}
int query(int o, int l, int r, int L, int R){
if(!o) return 0;
if(L<=l && r<=R) return tr[o].sum;
int mid=l+r>>1, ret=0;
if(L<=mid) ret+=query(son(o,0),l,mid,L,R);
if(R>mid) ret+=query(son(o,1),mid+1,r,L,R);
return ret;
}
}using namespace PT;
namespace DSU{
int fa[N];
void init(){
for(int i=1; i<=n; ++i) fa[i]=i;
}
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
}using namespace DSU;
int main(){
n=read(), m=read(), online=read();
for(int i=1; i<=m; ++i) a[i].u=read(), a[i].v=read(), a[i].w=read();
sort(a+1,a+m+1,cmp);
init();
int fu,fv;
for(int i=1; i<=m; ++i){
rt[a[i].w]=rt[a[i-1].w];
fu=find(a[i].u), fv=find(a[i].v);
if(fu==fv){
q=cutMax(a[i].u,a[i].v);
ins(rt[a[i].w],rt[a[i].w],1,a[1].w,LCT::tr[q].v,-LCT::tr[q].v);
}
else{
DSU::fa[fv]=fu;
q=n+i;
}
LCT::tr[q].v=a[i].w;
LCT::tr[q].mx_id=q;
link(a[i].u,q), link(q,a[i].v);
ins(rt[a[i].w],rt[a[i].w],1,a[1].w,a[i].w,a[i].w);
}
for(int i=a[1].w-1; i>0; --i)
if(rt[i]==0) rt[i]=rt[i+1];
q=read();
int l,r,lastans=0;
while(q--){
l=read()-online*lastans, r=read()-online*lastans;
printf("%d\n",lastans=query(rt[l],1,a[1].w,1,r));
}
return 0;
}
/*
5 7 1
1 2 2
2 3 4
3 4 3
4 5 1
5 1 3
2 5 4
1 4 5
5
1 2
4 7
11 12
11 13
18 19
*/
【bzoj 4046 加强版】Pork barrel的更多相关文章
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- Bzoj3930: [CQOI 2015] 选数 & COGS2699: [CQOI 2015] 选数加强版
题面 Bzoj COGS加强版 Sol 非加强版可以枚举AC这里不再讲述 设\(f(i)\)表示在\([L, H]\)取\(N\)个,\(gcd为i\)的方案数 \(F(i)=\sum_{i|d}f( ...
- BZOJ.3673/3674.可持久化并查集(可持久化线段树 按秩合并/启发式合并)
BZOJ 3673 BZOJ 3674(加强版) 如果每次操作最多只修改一个点的fa[],那么我们可以借助可持久化线段树来O(logn)做到.如果不考虑找fa[]的过程,时空复杂度都是O(logn). ...
- 洛谷 P2056 BZOJ 2743 [HEOI2012]采花
//表示真的更喜欢洛谷的题面 题目描述 萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 ...
- CERC 2014 (动态树+主席树)
CERC 2014 Pork barrel Problem : n个点m条边有边权的无向图,有q个询问,每次询问权值在[L,R]内的边组成的最小生成树的权值和,强制在线. n <= 1000, ...
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 635 Solved: 177[Submit][Stat ...
- bzoj 2594: [Wc2006]水管局长数据加强版 动态树
2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec Memory Limit: 128 MBSubmit: 934 Solved: 291[Submit][Sta ...
- BZOJ 3674 可持久化并查集加强版(路径压缩版本)
/* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...
- BZOJ 3674 可持久化并查集加强版(按秩合并版本)
/* bzoj 3674: 可持久化并查集加强版 http://www.lydsy.com/JudgeOnline/problem.php?id=3674 用可持久化线段树维护可持久化数组从而实现可持 ...
随机推荐
- paramiko实现登录主机
Paramiko模块使用 实现目的:192.168.0.61通过Paramiko模块登录192.168.0.63 一.下载安装 由于 paramiko 模块内部依赖pycrypto,所以先下载安装py ...
- 记一次flannel调试
今天发现k8s集群中不同Node上的pod不能互相ping通.调试了很长时间,发现是flannel的问题,记之. 问题一:对flannel backend的选择 flannel支持多种backend, ...
- 惊讶!我定的日志规范被CTO在全公司推广了
打印日志是一门艺术,但长期被开发同学所忽视.日志就像车辆保险,没人愿意为保险付钱,但是一旦出了问题都又想有保险可用.我们打印日志的时候都很随意,可是用的时候会吐槽各种 SB 包括自己!写好每一条日志吧 ...
- XCTF (app2)
打开app,有两个输入框和一个按钮.点击按钮会跳转到新的页面显示Waiting for you. 打开JEB反编译. 如果两个输入框的长度都不为0,那么获取这两个值到v0和v1中,Log记录日志. 创 ...
- keys随机生成
随机keys生成 const fs=require('fs'); const KEY_LEN=1024; const KEY_COUNT=2048; const CHARS='abcdefghijkl ...
- 调用redis封装好的JedisUtils接口实现锁库
1.在进行数据库操作的方法前先定义一个key值,并添加一个能区别每个key的标识 2.首先判断如果定义的key值存在的话,就直接return方法,如果不存在的话,就把key值放在jedisutil中, ...
- PJzhang:python基础入门的7个疗程-four
猫宁!!! 参考链接:易灵微课-21天轻松掌握零基础python入门必修课-售价29元人民币 https://www.liaoxuefeng.com/wiki/1016959663602400 第十天 ...
- Java架构师 -- 知识库
1,CSDN知识库: http://lib.csdn.net/base/architecture 2,淘宝
- EditText inputType类型整理
//文本类型,多为大写.小写和数字符号. android:inputType="none"//输入普通字符 android:inputType="text& ...
- PreparedStatement 以及事务的注意事项
a).PreparedStatement 可以进行批量操作,但是与Statement有一定的区别 1. Statement可以进行不同sql语句的批量操作 即可以同时进行 crud 操作. Strin ...