Luogu 3665 [USACO17OPEN]Switch Grass 切换牧草
BZOJ 4777 被权限了。
这道题的做法看上去不难,但是感觉自己yy不出来。
首先是两个结论:
1、答案一定是连接着两个异色点的一条边。
2、答案一定在最小生成树上。
感觉看到了之后都比较显然,自己想……算了吧……想不出来的……
那么我们可以对每一个点开一个以颜色为下标的线段树,对这棵树存一存它儿子的颜色到它的距离,然后在叶子结点维护一个$multiset$,把所有颜色相同的点都丢进去,然后维护一个最小值$lst_x = min(query(1, 1, k, 1, col_x - 1), query(1, 1, n, col_x + 1, k))$。
再全局维护一个$multiset$,每一次更改颜色的时候加入删除就好了。
时间复杂度$O(nlog^2n)$。
在Luogu上需要氧气。
Code:
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = 2e5 + ;
const int inf = << ; int n, m, k, qn, col[N], ufs[N], tot = , head[N];
int lst[N], idCnt = , id[N * ], fa[N], eVal[N];
multiset <int> ans, w[N * ]; struct Pathway {
int u, v, val; friend bool operator < (const Pathway &x, const Pathway &y) {
return x.val < y.val;
} } pat[N]; struct Edge {
int to, nxt, val;
} e[N << ]; inline void add(int from, int to, int val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} inline void addEdge(int x, int y, int v) {
add(x, y, v), add(y, x, v);
} inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} int find(int x) {
return x == ufs[x] ? x : ufs[x] = find(ufs[x]);
} inline void kruskal() {
sort(pat + , pat + + m);
int cnt = ;
for(int i = ; i <= n; i++) ufs[i] = i;
for(int i = ; i <= m; i++) {
int u = find(pat[i].u), v = find(pat[i].v);
if(u == v) continue;
ufs[u] = v;
addEdge(pat[i].u, pat[i].v, pat[i].val);
++cnt;
if(cnt >= n - ) break;
}
} inline int min(int x, int y) {
return x > y ? y : x;
} inline void chkMin(int &x, int y) {
if(y < x) x = y;
} namespace SegT {
struct Node {
int lc, rc, mn;
} s[N * ]; int root[N], nodeCnt = ; #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define mn(p) s[p].mn
#define mid ((l + r) >> 1) inline void up(int p) {
mn(p) = min(mn(lc(p)), mn(rc(p)));
} void ins(int &p, int l, int r, int x, int v) {
if(!p) mn(p = ++nodeCnt) = inf;
if(l == r) {
if(!id[p]) id[p] = ++idCnt;
w[id[p]].insert(v);
mn(p) = *(w[id[p]].begin());
return;
} if(x <= mid) ins(lc(p), l, mid, x, v);
else ins(rc(p), mid + , r, x, v);
up(p);
} void del(int &p, int l, int r, int x, int v) {
if(l == r) {
w[id[p]].erase(w[id[p]].find(v));
if(w[id[p]].empty()) mn(p) = inf;
else mn(p) = *(w[id[p]].begin());
return;
} if(x <= mid) del(lc(p), l, mid, x, v);
else del(rc(p), mid + , r, x, v);
up(p);
} int query(int p, int l, int r, int x, int y) {
if(!p) return inf;
if(x <= l && y >= r) return mn(p); int res = inf;
if(x <= mid) chkMin(res, query(lc(p), l, mid, x, y));
if(y > mid) chkMin(res, query(rc(p), mid + , r, x, y));
return res;
} } using namespace SegT; inline int queryMin(int x) {
int res = inf;
if(col[x] != ) chkMin(res, query(root[x], , k, , col[x] - ));
if(col[x] != k) chkMin(res, query(root[x], , k, col[x] + , k));
return res;
} void dfs(int x, int fat) {
fa[x] = fat;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
eVal[y] = e[i].val;
ins(root[x], , k, col[y], e[i].val);
dfs(y, x);
}
if(root[x]) {
lst[x] = queryMin(x);
ans.insert(lst[x]);
}
} int main() {
// freopen("2.in", "r", stdin);
// freopen("my.out", "w", stdout); read(n), read(m), read(k), read(qn);
for(int i = ; i <= m; i++)
read(pat[i].u), read(pat[i].v), read(pat[i].val);
kruskal(); for(int i = ; i <= n; i++) read(col[i]); mn() = inf;
dfs(, ); for(int x, v; qn--; ) {
read(x), read(v);
int pre = col[x];
col[x] = v;
if(root[x]) {
ans.erase(ans.find(lst[x]));
lst[x] = queryMin(x);
ans.insert(lst[x]);
}
if(fa[x]) {
ans.erase(ans.find(lst[fa[x]]));
del(root[fa[x]], , k, pre, eVal[x]);
ins(root[fa[x]], , k, v, eVal[x]);
lst[fa[x]] = queryMin(fa[x]);
ans.insert(lst[fa[x]]);
} printf("%d\n", *(ans.begin()));
}
return ;
}
Luogu 3665 [USACO17OPEN]Switch Grass 切换牧草的更多相关文章
- P3665 [USACO17OPEN]Switch Grass
		
题目描述 N个点M条边的无向图,每个点有一个初始颜色,每次改变一个点的颜色,求改变后整张图上颜色不同的点之间的距离最小值. 思路 考虑整张图的距离最小值一定是一条边,而不可能是一条路径,那么显然这条边 ...
 - BZOJ 4777: [Usaco2017 Open]Switch Grass
		
4777: [Usaco2017 Open]Switch Grass Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 46 Solved: 10[Su ...
 - js使用Switch达到切换不同颜色的效果
		
实现的效果,点击哪个,哪个变颜色,效果如下. 代码如下: <!DOCTYPE html> <html> <head> <meta charset=" ...
 - BZOJ 4777 Usaco2017 Open Switch Grass Kruskal+替罪羊树+权值线段树
		
这道题首先可以看出答案一定是一条边,而且答案一定在最小生成树上,那么我们就可以在这个最小生成树上维护他与异色儿子的边最小值,所以我们就可以已通过Kruskal和一棵平衡树来解决,时间复杂度是O(n*l ...
 - BZOJ 3887/Luogu P3119: [Usaco2015 Jan]Grass Cownoisseur (强连通分量+最长路)
		
分层建图,反向边建在两层之间,两层内部分别建正向边,tarjan缩点后,拓扑排序求一次1所在强连通分量和1+n所在强联通分量的最长路(长度定义为路径上的强联通分量内部点数和).然后由于1所在强连通分量 ...
 - BZOJ4777 [Usaco2017 Open]Switch Grass[最小生成树+权值线段树套平衡树]
		
标题解法是吓人的. 图上修改询问,不好用数据结构操作.尝试转化为树来维护.发现(不要问怎么发现的)最小生成树在这里比较行得通,因为最近异色点对一定是相邻的(很好想),所以只要看最短的一条两端连着异色点 ...
 - switch host 切换本地host
		
百度网盘提取地址 提取码: 753r 下载后放到软件目录即可使用
 - [bzoj4777]Switch Grass
		
结论:最短路径一定是单独的一条边且在最小生成树上,可以用反证法证明.那么求出最小生成树,对于每一个点建立一棵权值线段树,再对每一个权值线段树上的叶子节点开一个multiset,维护所有儿子中该种颜色的 ...
 - flat ui switch 改变状态而不响应事件
		
Flat UI是一套精美的扁平风格 UI 工具包,基于 Twitter Bootstrap实现.这套界面工具包含许多基本的和复杂的 UI 部件,例如按钮,输入框,组合按钮,复选框,单选按钮,标签,菜单 ...
 
随机推荐
- 剑指offer-第二章数据结构(数组,字符串,链表,树,栈与队列)及例题
			
一.数组(最简单的数据结构) 定义:占据一块连续内存并按照顺序存储数据.创建时先指定大小,分配内存. 优点:时间效率高.实现简单的hash(下标为key,对应的数据为value) 缺点:空间效率差.如 ...
 - 【转】C# Socket编程(4)初识Socket和数据流
			
[转自:https://www.cnblogs.com/IPrograming/archive/2012/10/15/CSharp_Socket_4.html] 经过前面基础知识作为背景,现在对Soc ...
 - 向HDFS中追加内容
			
向生成好的hdfs文件中追加内容,但是线上使用的版本是1.0.3,查看官方文档发现,在1.0.4版本以后才支持文件append 以下是向hdfs中追加信息的操作方法 如果你只在某一个driver中追加 ...
 - 数据库模型类转换实体类的dbToPojoUtil工具类开发
			
idea颜色说明http://blog.csdn.net/saindy5828/article/details/53319693 1,中途运用了properties,properties.getPro ...
 - 17.Selenium+Python日期控件小案例
			
1.web上的控件种类十分多,但是大致分为2种,一种为类型是input的且可以输入,第二种为类型是input的且属性为readonly,文本框不可编辑 2.第一种类型为可以输入的,直接send_key ...
 - Python 字典 列表 嵌套 复杂排序大全
			
https://blog.csdn.net/ray_up/article/details/42084863 一: 字典排序 解析: 使用sorted 方法, 排序后的结果为一个元组. 可以字符串排序( ...
 - maven命令行创建web项目报错:java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils
			
早上一上班就想新建一个web项目玩玩,没想到一敲命令创建就失败了,真是出师不利.各种折腾无果,当然我也可以用eclipse直接创建的,就是不甘心被这破问题给耍了.刚刚才发现问题原因,这个结果我也是醉了 ...
 - Linux 多路复用 select / poll
			
多路复用都是在阻塞模式下有效! linux中的系统调用函数默认都是阻塞模式,例如应用层读不到驱动层的数据时,就会阻塞等待,直到有数据可读为止. 问题:在一个进程中,同时打开了两个或者两个以上的文件,读 ...
 - Linux I/O 映射(ioremap)和writel/readl
			
在裸奔代码中,如果要控制gpio,直接控制gpio寄存器地址即可: 在linux系统中,所有操作的地址都是虚拟地址,都是由linux内核去管理,所以需要将物理地址转换成内核可识别的虚拟地址. 1.io ...
 - java 执行bat批处理文件 并关闭cmd窗口
			
java 执行bat批处理文件 并关闭cmd窗口 import java.io.IOException; public class CmdMain { public static void main( ...