题目描述

  给你一个\(n\)个点\(m\)条边图,\(q\)个询问,每次问你边权在\([l,r]\)之间的边组成的最小生成树(森林)的边权和。强制在线。

  \(n,m,q\leq 100000\)

题解

  考虑离线做法。从大到小加边,用LCT维护当前的最小生成树。维护一棵线段树,第\(i\)个位置表示当前的最小生成树中边权为\(i\)的边的权值和。当一条边被加入时就在对应位置加上边权,删掉时就减掉边权。假设已经处理了边权\(\geq i\)的所有边,那么对于所有\(l=i\)的询问的答案就是线段树中\([1,r]\)的数和(等价于\([l,r]\),因为\([1,l-1]\)都是空的)。

  把这棵线段树变成可持久化线段树就可以在线处理询问了。

  我也不知道为什么边权范围是\([1,10000]\)。

  时间复杂度:\(O((m+q)\log n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace lct
{
int f[200010];
int a[200010][2];
pii s[200010];
pii v[200010];
int rev[200010];
void reverse(int x)
{
rev[x]^=1;
swap(a[x][0],a[x][1]);
}
void push(int x)
{
if(rev[x])
{
if(a[x][0])
reverse(a[x][0]);
if(a[x][1])
reverse(a[x][1]);
rev[x]=0;
}
}
void mt(int x)
{
s[x]=v[x];
if(a[x][0])
s[x]=max(s[x],s[a[x][0]]);
if(a[x][1])
s[x]=max(s[x],s[a[x][1]]);
}
int root(int x)
{
return !f[x]||(a[f[x]][0]!=x&&a[f[x]][1]!=x);
}
void rotate(int x)
{
if(root(x))
return;
int p=f[x];
int q=f[p];
int ps=(x==a[p][1]);
int qs=(p==a[q][1]);
int ch=a[x][ps^1];
if(!root(p))
a[q][qs]=x;
a[x][ps^1]=p;
a[p][ps]=ch;
if(ch)
f[ch]=p;
f[p]=x;
f[x]=q;
mt(p);
mt(x);
}
void pushdown(int x)
{
if(!root(x))
pushdown(f[x]);
push(x);
}
void splay(int x)
{
pushdown(x);
while(!root(x))
{
int p=f[x];
if(!root(p))
{
int q=f[p];
if((x==a[p][1])^(p==a[q][1]))
rotate(x);
else
rotate(p);
}
rotate(x);
}
}
void access(int x)
{
int y=x,t=0;
while(x)
{
splay(x);
a[x][1]=t;
mt(x);
t=x;
x=f[x];
}
splay(y);
}
void change(int x)
{
access(x);
reverse(x);
}
void link(int x,int y)
{
change(x);
f[x]=y;
}
void cut(int x,int y)
{
change(x);
access(y);
f[a[y][0]]=0;
a[y][0]=0;
}
pii query(int x,int y)
{
change(x);
access(y);
return s[y];
}
int findroot(int x)
{
access(x);
while(a[x][0])
x=a[x][0];
splay(x);
return x;
}
}
namespace seg
{
int n=0;
int ls[5000010];
int rs[5000010];
int s[5000010];
int rt[100010];
int change(int p1,int x,int v,int l,int r)
{
int p=++n;
ls[p]=ls[p1];
rs[p]=rs[p1];
s[p]=s[p1]+v;
if(l==r)
return p;
int mid=(l+r)>>1;
if(x<=mid)
ls[p]=change(ls[p1],x,v,l,mid);
if(x>mid)
rs[p]=change(rs[p1],x,v,mid+1,r);
return p;
}
int query(int p,int l,int r,int L,int R)
{
if(l<=L&&r>=R)
return s[p];
int mid=(L+R)>>1;
int res=0;
if(l<=mid)
res+=query(ls[p],l,r,L,mid);
if(r>mid)
res+=query(rs[p],l,r,mid+1,R);
return res;
}
}
struct edge
{
int x,y,d;
};
int cmp(edge a,edge b)
{
return a.d<b.d;
}
edge a[100010];
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
int n,m,on;
scanf("%d%d%d",&n,&m,&on);
int i;
for(i=1;i<=m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].d);
sort(a+1,a+m+1,cmp);
int j=m;
seg::rt[n+1]=0;
for(i=1;i<=n;i++)
lct::v[i]=pii(0,0);
for(i=10000;i>=1;i--)
{
seg::rt[i]=seg::rt[i+1];
while(j>=1&&a[j].d==i)
{
int rx=lct::findroot(a[j].x);
int ry=lct::findroot(a[j].y);
if(rx==ry)
{
pii s=lct::query(a[j].x,a[j].y);
if(s.first>a[j].d)
{
lct::cut(a[s.second].x,s.second+n);
lct::cut(a[s.second].y,s.second+n);
lct::v[j+n]=pii(a[j].d,j);
lct::link(a[j].x,j+n);
lct::link(a[j].y,j+n);
seg::rt[i]=seg::change(seg::rt[i],s.first,-s.first,1,10000);
seg::rt[i]=seg::change(seg::rt[i],a[j].d,a[j].d,1,10000);
}
}
else
{
lct::v[j+n]=pii(a[j].d,j);
lct::link(a[j].x,j+n);
lct::link(a[j].y,j+n);
seg::rt[i]=seg::change(seg::rt[i],a[j].d,a[j].d,1,10000);
}
j--;
}
}
int q;
scanf("%d",&q);
int l,h,last=0;
for(i=1;i<=q;i++)
{
scanf("%d%d",&l,&h);
l-=on*last;
h-=on*last;
last=seg::query(seg::rt[l],1,h,1,10000);
printf("%d\n",last);
}
return 0;
}

【XSY2528】道路建设 LCT 可持久化线段树的更多相关文章

  1. 【bzoj3514】Codechef MARCH14 GERALD07加强版 LCT+可持久化线段树

    题目描述 N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 输入 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M行,代表图中的每条边 ...

  2. bzoj 3514: GERALD07加强版 lct+可持久化线段树

    题目大意: N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 题解: 这道题考试的时候没想出来 于是便爆炸了 结果今天下午拿出昨天准备的题表准备做题的时候 题表里就有这题 ...

  3. BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT+可持久化线段树

    自己独自想出来并切掉还是很开心的~ Code: #include <bits/stdc++.h> #define N 400005 #define inf 1000000000 #defi ...

  4. HDU 5820 (可持久化线段树)

    Problem Lights (HDU 5820) 题目大意 在一个大小为50000*50000的矩形中,有n个路灯.(n<=500000) 询问是否每一对路灯之间存在一条道路,使得长度为|x1 ...

  5. 【BZOJ4704】旅行 树链剖分+可持久化线段树

    [BZOJ4704]旅行 Description 在Berland,有n个城堡.每个城堡恰好属于一个领主.不同的城堡属于不同的领主.在所有领主中有一个是国王,其他的每个领主都直接隶属于另一位领主,并且 ...

  6. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

  7. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  8. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

  9. HDU 4866 Shooting(持久化线段树)

    view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...

随机推荐

  1. Jenkins- job之间传参

    前言: 本文介绍插件: Parameterized Trigger plugin的具体使用方法. 一.插件介绍 Parameterized Trigger plugin插件可以让你在构建完成时触发新的 ...

  2. Python Revisited Day 01

    逻辑操作符 身份操作符 is a = ['AAA', 3, None] b = ['AAA', 3, None] a is b #False b = a a is b #True 身份比较速度快,原因 ...

  3. c++入门之命名空间存在的意义

    看过鸡啄米的C++编程入门系列教程的朋友,应该能注意到,在其中的很多实例中,都有这么一条语句:using namespace std;,即使用命名空间std,其作用就是规定该文件中使用的标准库函数都是 ...

  4. Django 2.0 学习

    Django django是基于MTV结构的WEB框架 Model 数据库操作 Template 模版文件 View 业务处理 在Python中安装django 2.0 1 直接安装 pip inst ...

  5. static特别用法【静态导包】——Java包的静态导入

    面试我问你static关键字有哪些作用,如果你答出static修饰变量.修饰方法我会认为你合格,答出静态块,我会认为你不错,答出静态内部类我会认为你很好,答出静态导包我会对你很满意,因为能看出你非常热 ...

  6. Git使用过程中的问题

    Q-1:怎么切换到远程的分支 本地已经有一个代码库了(是从github上clone的),但是现在远程库中一个新的branch,怎么拉取远程分支,并在本地创建该分支(内容一样).how to do? # ...

  7. array_filter与array_map

    php数组array_filter函数和array_slice函数:<?php /* array_filter()用回调函数过滤数组中的单元 array_filter(array,functio ...

  8. [转帖]Docker save and load镜像保存

    Docker save and load镜像保存 https://www.cnblogs.com/zhuochong/p/10064350.html docker save 和 load 以及 imp ...

  9. ActiveMQ入门案例-生产者代码实现

    <–start–> 使用Java程序操作ActiveMQ生产消息,代码的复杂度较高,但也没有默写下来的必要. 开发ActiveMQ首先需要导入activemq-all.jar包,如果是ma ...

  10. mybatis两种开发方式

    本文首先讲解从JDBC到mybatis的演变过程,然后是使用mybatis进行开发的两种方式. 一 JDBC的使用及其优化 1.使用JDBC进行数据库操作 加载JDBC驱动: 建立并获取数据库连接: ...