题解:P3544 [POI 2012] BEZ-Minimalist Security

news/2025/3/12 12:33:09/文章来源:https://www.cnblogs.com/kkxacj/p/18717921

前言

模拟赛中因为判无解判错了错一个点再次喜提 \(0\) 分。

思路

不难想到,对于一个联通块,确定一个点的值,这个联通块其它的点的值都确定了,当然无法确定就是无解。

考虑优化上诉过程,容易发现合法的取值一定是一段区间,我们想做到在 \(i\) 最终值为 \(0\) 时,最少加多少会合法,最多加多少会合法,我们二分图染色,与 \(i\) 颜色一样的记为 \(+1\),不一样的记为 \(-1\),其和就是每次 \(i\) 值增加会新增的值。

我们给每个点记录两个 \(\verb!vector!\),分别表示一些会增加的量和一些会减少的量,举个例子,我们设 \(b_i\) 为颜色,我们设根节点颜色为 \(1\),在 \(b_i = 1\) 时,与 \(i\) 相邻的点 \(j\) 边权为 \(z\)\(j\) 就会加入一个会减少的量 \(z-a_i\)\(b_i = 0\) 就加入一个会减的,可以理解为插入一条直线。

我们现在来考虑每个点会造成的影响,如果它又有斜率为正的直线又有斜率为负的直线,就看一下是否存在一个时刻,所有直线交于一点,没有就无解。

同时对于每一条直线,我们要找出它在那一段区间合法,然后更新左右端点,最后在求答案时,把无解判掉即可,详情可以看题解,有注释。

code

#include<bits/stdc++.h>
#define int long long
using namespace std;
#define getchar() (p1 == p2 && (p2 = (p1 = buf1) + fread(buf1, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf1[1 << 23], *p1 = buf1, *p2 = buf1, ubuf[1 << 23], *u = ubuf;
namespace IO
{template<typename T>void read(T &_x){_x=0;int _f=1;char ch=getchar();while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar();while(isdigit(ch)) _x=_x*10+(ch^48),ch=getchar();_x*=_f;}template<typename T,typename... Args>void read(T &_x,Args&...others){Read(_x);Read(others...);}const int BUF=20000000;char buf[BUF],to,stk[32];int plen;#define pc(x) buf[plen++]=x#define flush(); fwrite(buf,1,plen,stdout),plen=0;template<typename T>inline void print(T x){if(!x){pc(48);return;}if(x<0) x=-x,pc('-');for(;x;x/=10) stk[++to]=48+x%10;while(to) pc(stk[to--]);}
}
using namespace IO;
const int N = 5e5+10,M = 3e6+10;
int n,m,a[N],head[N],d[N],v[N],v2[N],t[2],st[N],cnt,x,y,z,l,r,mid,ans,ans1,sum2,sum3,sum,sum1,mi,mx,op,op1,op2;
vector<int>v1[N],V1[N];
/*
v1:存储斜率为正的直线
V1:存储斜率为负的直线
t_i:颜色i出现几次
st:联通快出现的点 
*/ 
struct w1
{int to,nxt,z;
}b[M<<1];
inline void add(int x,int y,int z)
{b[++cnt].nxt = head[x];b[cnt].to = y,b[cnt].z = z;head[x] = cnt;
}
void dfs(int x,int y)
{v[x] = 1; v2[x] = !v2[y]; st[++cnt] = x; t[v2[x]]++; sum2 += d[x];for(int i = head[x];i;i = b[i].nxt){if(!v[b[i].to]) d[b[i].to] = b[i].z-d[x],dfs(b[i].to,x);//dfs gen xin da anif(v2[x] == 1) v1[b[i].to].push_back(b[i].z-d[x]);//yi ge hui jian de shuelse V1[b[i].to].push_back(b[i].z-d[x]);//yi ge hui jia de shu}
}
signed main()
{
//	freopen("add.in","r",stdin);
//	freopen("add.out","w",stdout);read(n),read(m);for(int i = 1;i <= n;i++) read(a[i]),sum3 += a[i];for(int i = 1;i <= m;i++) read(x),read(y),read(z),add(x,y,z),add(y,x,z); for(int i = 1;i <= n;i++)if(!v[i]){d[i] = cnt = 0;mi = 1e16,mx = 0,op = -1e16; t[0] = t[1] = 0; sum2 = 0;V1[i].push_back(0); dfs(i,0);for(int j = 1;j <= cnt;j++) {x = st[j];for(int z = 0;z < v1[x].size();z++) mx = max(mx,v1[x][z]-a[x]),mi = min(mi,v1[x][z]);//hui jian defor(int z = 0;z < V1[x].size();z++) mx = max(mx,-V1[x][z]),mi = min(mi,a[x]-V1[x][z]);//hui jia deif(v1[x].size() != 0 && V1[x].size() != 0){op1 = -1e16;for(int z = 0;z < v1[x].size();z++){if(op1 == -1e16) op1 = v1[x][z];else if(op1 != v1[x][z]){ op1 = -1e17; break; }}if(op1 == -1e17) { op == -1e17; break; }//1:多个斜率相同的直线且初值不一样,永不相交 op2 = -1e16;for(int z = 0;z < V1[x].size();z++){if(op2 == -1e16) op2 = V1[x][z];else if(op2 != V1[x][z]){ op2 = -1e17; break; }}//同上 || 两个无法某一刻相同 || 上升的初值比下降的初值大,不相交 if(op2 == -1e17 || (op1-op2)%2==1 || op2 > op1) { op = -1e17; break; }if(op == -1e16 || op == (op1-op2)/2) op = (op1-op2)/2;else { op == -1e17; break; }//2:多个必须选的点,无解 }}//mx,op,miif(op == -1e17) { printf("NIE"); return 0; } if(mx > mi) { printf("NIE"); return 0; }//3:左端点大于右端点,无解 if(op != -1e16 && (mx > op || op > mi)) { printf("NIE"); return 0; }//4:必须选的点不在区间里面,无解 if(op != -1e16) ans = ans1 = op*(t[1]-t[0])+sum2;//选取的点确定了 else ans = mi*(t[1]-t[0])+sum2,ans1 = mx*(t[1]-t[0])+sum2;//最大值和最小值一定是两个端点,哪个最大哪个最小不重要,加的时候取min,max就好了 sum += max(ans,ans1),sum1 += min(ans,ans1);}print(sum3-sum),pc(' '),print(sum3-sum1),pc('\n');flush();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/884650.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c_note

c笔记一、变量 1、变量的声明 ​ 变量的声明是给编译器看的,告诉编译器变量的类型以及名字等相关的信息。 格式:数据类型 变量名; 变量的声明显然是一个编译时概念,所以它和程序的运行没有太大的关系。 一个变量具有声明,并不意味着该变量会在运行时期分配内存空间。 2、…

Drasi Sources SDK

什么是Drasi数据源(Source)?Source提供了与系统的连接,Drasi 可以将这些系统视为变化源。source 在 Drasi 中执行三个重要功能:处理源系统生成的更改日志/源,并将这些更改推送到使用该源作为输入的每个连续查询。 将源更改数据转换为一致的属性图数据模型,以便订阅的 Co…

【每日一题】20250216

人生就是这样,不经历鲜血淋漓的疼痛,就不会明白那些曾经让我们厌烦的说教其实是受用一生的信条。【每日一题】(多选)如图所示,在竖直半面内有一半径为 \(R\) 的圆弧轨道.半径 \(OA\) 木平、\(OB\) 竖直,一个质量为 \(m\) 的小球自 \(A\) 的正上方 \(P\) 点由静止开始自由…

数据团队必读:智能数据分析文档(DataV Note)五种高效工作模式

数据项目,无论是数据分析、可视化,还是数据科学和机器学习相关的项目,通常都非常复杂,涉及多个组成部分,比如代码、数据、运行环境、SQL脚本以及分析报告等;与此同时,随着AI时代的到来,数据科学领域正经历重大变革。这对于数据科学团队来说,如何保持高效地工作模式一直…

SU镜像:缩放s

su没有镜像,可用:缩放s 选中要镜像的对象——复制一个——s——找到中间的点——向右拉动——输入 -1

LGP1377 [TJTS 2011] 树的序 学习笔记

LGP1377 [TJTS 2011] 树的序 学习笔记 Luogu Link 题意简述 给一个生成序列 \(p\),简单起见 \(p\) 是一个长为 \(n\) 的排列。按照这样的步骤生成一棵二叉搜索树:往空树中插入 \(p_i\),则 \(p_i\) 成为当前二叉搜索树的根。 往非空树 \(u\) 中插入 \(p_i\),若 \(p_i\) 小于…

vxe-input绑定keyup事件传递的参数

一、VUE3中 Input输入框绑定keyup事件传递的$event 代码一:<script setup>function judgeIsEnterToSerach(event){console.log(event,1111);console.log(event.key,2222);console.log(event.target,230923);console.log(event.target.value,3333);console.log(event.tar…

清华大学推出第二讲 DeepSeek 如何赋能职场应用?从提示语技巧到多场景应用!

前言 清华大学第二讲《DeepSeek如何赋能职场应用》是一份35页的专业文档,详细探讨了DeepSeek在职场中的多场景应用及其赋能作用,从提示语技巧到多场景应用,咱们打工人有福啦!DeepSeek访问地址:https://chat.deepseek.com 清华大学推出的 DeepSeek 从入门到精通(104页)免…

信创

概念 “信创“ (全称“信息技术应用创新”)是国家基于国产芯片和操作系统的PC、服务器、网络设备、存储设备、数据库、中间件等基础设施的技术创新。 信创CPU概览

LGP5854 [LG TPLT] 笛卡尔树 学习笔记

LGP5854 [LG TPLT] 笛卡尔树 学习笔记 Luogu Link 题意简述 给定一个长为 \(n\) 的排列 \(p\),以 \(i\) 为键,\(p_i\) 为值构建 \(p\) 中所有元素的笛卡尔树。 做法解析 定义“右链”为从根开始一直往右儿子走形成的一条链。 因为我们照键从小到大的顺序插入每一个元素,所以…

11.4.3 凸目标的收敛性分析

式\((11.47)\)应该有误,不等号左边还应该有一个项\(-E[||x_T-x^{*}||^2]\),之所以没写估计是因为认为\(x_T\)非常接近\(x^{*}\),所以可以忽略;另外不等号右边的括号打错了,应该是 \[2\underset{t=1}{\overset{T}{\sum}}\eta_tE[R(x_t)]-2S_1R^*-S_2L^2 \],其中\(S_1=\und…

AGC053C 题解

Solution 前面部分略,相信别的题解写得很详细。 本题解集中解释 \(p(d)\) 的计算。 \(p(d)\) 表示对于 \(\forall A_i\),\(B_1\cdots B_{i+d}\) 中有比它大的数。 那么这么考虑,已经加入 \(A_1 \cdots A_{i-1}\)。对于 \(A_i\) ,如果大于 \(\min(A_1 \cdots A_{i-1},B_1 \c…