4777: [Usaco2017 Open]Switch Grass

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 46  Solved: 10
[Submit][Status][Discuss]

题目:给定一张带权无向图,每个点有一个颜色,每次改变一个点的颜色,要求你在操作后输出这个图中最近异色点对之间的距离最近异色点对定义为:一对点颜色不同,且距离最小。

数据范围:N个点,M条无向边,Q次修改,颜色范围[1,k],边权L。N,M,Q≤200000,K≤N,1≤L≤10.

想法:

发现1:答案肯定是某一边权。因为边权大于0,答案路径上肯定是先经过若干个相同颜色的点,最后再碰到不相同。所以只要取这条路径的末端两个点就好了....

发现2:对于原图的答案等价于其最小生成树图的答案。因为在一个环上,最大边权只可能变劣(画图看看嘛),满足最小生成树环切性。

所以问题变成了:给你一棵最小生成树,询问该时刻相邻异色点距离最小是多少。

在线搞:既然是棵树,每个节点用堆/set存下每个颜色中其儿子节点的距离。剩下好像就很明了....

离线搞:考虑一条边什么时候会作为答案。按边权从小到大考虑每条边,用并查集跳过已经有边的时间。用双向链表维护一个点的颜色时间段。

复杂度:O(n+q+mlogm) 如果用基数排序也许是线性算法?

#include<cstdio>
#include<vector>
#include<algorithm> const int len();
struct Data{int last,col,pre,suc;}look_v,look_u,look;
std::vector<Data>Seg[len+];
struct ABC{int a,b,c;bool bf;}L[len+];
struct Node{int nd,nx;}bot[len*+];
int tot,first[len+],depth[len+];
int f[len+],ans[len+];
int n,m,k,q,x,y,col[len+],last[len+];
template <class T>void read(T &x)
{
x=;bool f=;char c=getchar();
while((c<''||c>'')&&c!='-')c=getchar(); if(c=='-')f=,c=getchar();
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
x=f?-x:x;
}
template <class T>T abs(T x){return x<?-x:x;}
template <class T>T min(T a,T b){return a>b?b:a;}
void swap(int &x,int &y){x^=y,y^=x,x^=y;}
bool cmp(ABC A,ABC B){return A.c<B.c;}
void add(int a,int b){bot[++tot]=(Node){b,first[a]};first[a]=tot;}
int gf(int x)
{
int v=x;while(f[v]!=v)v=f[v];
for(int o;x!=v;x=o)o=f[x],f[x]=v;
return v;
}
void Kruskal()
{
for(int i=,fa,fb;i<=m;i++)
{
fa=gf(L[i].a); fb=gf(L[i].b);
if(fa!=fb)
{
f[fa]=fb;
L[i].bf=true;
}
}
}
void union_Seg(int x,int v)
{
int pre=Seg[x][v].pre,suc=Seg[x][v].suc,t=gf(Seg[x][v].last);
look=Seg[x][v];
if(Seg[x][suc].last<=t)//中间这块不会再被访问到
{
Seg[x][pre].suc=suc;
Seg[x][suc].pre=pre;
if(Seg[x][pre].col==Seg[x][suc].col)
{
Seg[x][pre].suc=Seg[x][suc].suc;//合并颜色相同的
Seg[x][Seg[x][pre].suc].pre=pre;
}
}
}
int main()
{
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
read(n),read(m),read(k),read(q);
for(int i=;i<=m;i++) read(L[i].a),read(L[i].b),read(L[i].c);
for(int i=;i<=n;i++) read(col[i]),f[i]=i,last[i]=;//从零开始
std::sort(L+,L++m,cmp);
Kruskal();
for(int i=,sz;i<=q;i++)
{
read(x),read(y);
sz=Seg[x].size();
Seg[x].push_back((Data){last[x],col[x],sz-,sz+});
col[x]=y; last[x]=i; f[i]=i;
}
for(int i=,sz;i<=n;i++)
{
sz=Seg[i].size();
Seg[i].push_back((Data){last[i],col[i],sz-,sz+});
Seg[i].push_back((Data){q+,,,});//边界
}
f[q+]=q+;
for(int i=;i<=m;i++)
if(L[i].bf)
{
x=L[i].a,y=L[i].b;
for(int now=,v=,u=;now<=q;)
{
now=gf(now+); if(now>q)break;
look=Seg[x][v];
for(int suc=Seg[x][v].suc;Seg[x][suc].last<=now;)
look=Seg[x][suc],v=suc,suc=Seg[x][suc].suc;//可以被卡到O(q^2)
look=Seg[y][u];
for(int suc=Seg[y][u].suc;Seg[y][suc].last<=now;)
look=Seg[y][suc],u=suc,suc=Seg[y][suc].suc;//可以被卡到O(q^2)
look_v=Seg[x][v]; look_u=Seg[y][u];
if(Seg[x][v].col!=Seg[y][u].col)ans[now]=L[i].c,f[now]=now+;//共O(n)
else now=min(Seg[x][ Seg[x][v].suc ].last,Seg[y][ Seg[y][u].suc ].last)-;//可以被卡到O(q^2)
union_Seg(x,v); union_Seg(y,u);//合并 简化 以保证不被卡成O(q^2)
//合并后 v,u不变没影响
}
}
for(int i=;i<=q;i++)printf("%d %d\n",i,ans[i]);
return ;
}
 

BZOJ 4777: [Usaco2017 Open]Switch Grass的更多相关文章

  1. BZOJ 4777 Usaco2017 Open Switch Grass Kruskal+替罪羊树+权值线段树

    这道题首先可以看出答案一定是一条边,而且答案一定在最小生成树上,那么我们就可以在这个最小生成树上维护他与异色儿子的边最小值,所以我们就可以已通过Kruskal和一棵平衡树来解决,时间复杂度是O(n*l ...

  2. BZOJ4777 [Usaco2017 Open]Switch Grass[最小生成树+权值线段树套平衡树]

    标题解法是吓人的. 图上修改询问,不好用数据结构操作.尝试转化为树来维护.发现(不要问怎么发现的)最小生成树在这里比较行得通,因为最近异色点对一定是相邻的(很好想),所以只要看最短的一条两端连着异色点 ...

  3. Luogu 3665 [USACO17OPEN]Switch Grass 切换牧草

    BZOJ 4777 被权限了. 这道题的做法看上去不难,但是感觉自己yy不出来. 首先是两个结论: 1.答案一定是连接着两个异色点的一条边. 2.答案一定在最小生成树上. 感觉看到了之后都比较显然,自 ...

  4. bzoj 4780: [Usaco2017 Open]Modern Art 2

    4780: [Usaco2017 Open]Modern Art 2 Time Limit: 10 Sec  Memory Limit: 128 MB Description Having becom ...

  5. 洛谷—— P3119 [USACO15JAN]草鉴定Grass Cownoisseur || BZOJ——T 3887: [Usaco2015 Jan]Grass Cownoisseur

    http://www.lydsy.com/JudgeOnline/problem.php?id=3887|| https://www.luogu.org/problem/show?pid=3119 D ...

  6. 线段树合并 || 树状数组 || 离散化 || BZOJ 4756: [Usaco2017 Jan]Promotion Counting || Luogu P3605 [USACO17JAN]Promotion Counting晋升者计数

    题面:P3605 [USACO17JAN]Promotion Counting晋升者计数 题解:这是一道万能题,树状数组 || 主席树 || 线段树合并 || 莫队套分块 || 线段树 都可以写..记 ...

  7. BZOJ 4756 [Usaco2017 Jan]Promotion Counting(线段树合并)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4756 [题目大意] 给出一棵树,对于每个节点,求其子树中比父节点大的点个数 [题解] ...

  8. bzoj 4756 [Usaco2017 Jan]Promotion Counting——线段树合并

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4756 线段树合并裸题.那种返回 int 的与传引用的 merge 都能过.不知别的题是不是这 ...

  9. bzoj 4991 [Usaco2017 Feb]Why Did the Cow Cross the Road III(cdq分治,树状数组)

    题目描述 Farmer John is continuing to ponder the issue of cows crossing the road through his farm, intro ...

随机推荐

  1. ASPNET&nbsp;session客户端与服务…

    除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session.然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根 ...

  2. linux控制USB的绑定/解绑

    linux控制USB的绑定/解绑 http://www.jianshu.com/p/57293f9be558 今天工作中遇到一个问题, 要用代码实现USB的enable和disable. 谷歌了一番, ...

  3. Spring Boot实现学生信息增删改查

    上一篇博客写了如何初始化一个简单的Spring Boot项目,这次详细记录一下如何连接数据库并实现增删改查基本操作. 我使用的是MySQL 5.5+Navicat,MySQL量级比较轻,当然微软的SQ ...

  4. Spring Data JPA stackoverflow

    1.禁止使用lombok 的@Data 注释 使用@Data注释后,默认会重写父类的toString()方法,hashcode()等方法,在往map里存的时候,会根据equals和hashcode方法 ...

  5. MySQL数据库基础详解(非原创)

    文章大纲 一.数据库简介二.Mysql数据库简介三.Mysql安装与服务启动(Windows版本)四.Mysql图形化工具五.Mysql存储引擎精讲六.Mysql数据类型介绍七.Mysql主要专业名称 ...

  6. Git查询

    Git查询 查询分支 git branch # 查询本地分支 git branch -a # 查询所有分支 $ git branch -a * master remotes/origin/HEAD - ...

  7. poj3186(区间dp)

    题目链接:http://poj.org/problem?id=3186 题意:给一行n个数,每次可以取出行首或者行末的数,如果第ai是第i次取出的,可以得到ai*i的收益,求最大的总收益: 思路:区间 ...

  8. ajax对象。同步与异步及ajax发送请求

    ajax对象的属性.方法 属性 readyState: Ajax状态码 * 0:表示对象已建立,但未初始化,只是 new 成功获取了对象,但是未调用open方法 1:表示对象已初始化,但未发送,调用了 ...

  9. loadrunner教程系列

    loadrunner教程系列,包括windows 环境和linux 环境. 第一讲:环境准备 链接:https://pan.baidu.com/s/1EnLP3ijZ1j1I_ysE1z4CJg  密 ...

  10. [题解](prufer)明明的烦恼

    https://www.cnblogs.com/noip/archive/2013/03/10/2952520.html 以及高精(抄 #include<iostream> #includ ...