选举

博客介绍了小奇投票问题的两种思路。30分思路通过设f[i]和sum[i],根据不同条件更新f[i],复杂度为O(n∗(r−l+1))。100分思路考虑优化,用权值线段树维护sum值,动态维护该树,用优先队列维护sum的最大f值。

也许更好的阅读体验
D e s c r i p t i o n \mathcal{Description} Description
problem

data
S o l u t i o n \mathcal{Solution} Solution

30分思路

f [ i ] f[i] f[i]表示以 i i i结尾,划分的区间都合法时,小奇得票数比魔法猪最多多几票
s u m [ i ] sum[i] sum[i]表示支持情况的前缀和
j ∈ [ m a x ( i − r , 0 ) , m a x ( i − l , 0 ) ] j\in[max(i-r,0),max(i-l,0)] j[max(ir,0),max(il,0)]
s u m [ i ] = = s u m [ j ] sum[i]==sum[j] sum[i]==sum[j] f [ i ] = m a x ( f [ i ] , f [ j ] ) f[i]=max(f[i],f[j]) f[i]=max(f[i],f[j])
s u m [ i ]    >   s u m [ j ] sum[i]\ \ > \ sum[j] sum[i]  > sum[j] f [ i ] = m a x ( f [ i ] , f [ j ] + 1 ) f[i]=max(f[i],f[j]+1) f[i]=max(f[i],f[j]+1)
s u m [ i ]    &lt;   s u m [ j ] sum[i]\ \ &lt; \ sum[j] sum[i]  < sum[j] f [ i ] = m a x ( f [ i ] , f [ j ] − 1 ) f[i]=max(f[i],f[j]-1) f[i]=max(f[i],f[j]1)
复杂度 O ( n ∗ ( r − l + 1 ) ) O(n*(r-l+1)) O(n(rl+1))
代码就不贴了

100分思路

考虑优化30分思路,能否用数据结构把 ( r − l + 1 ) (r-l+1) (rl+1)的复杂度优化为 l o g log log级别
用一个权值线段树来维护每一个 s u m sum sum值,即权值线段树中的节点的意义为,若该节点表示区间 [ k , k ] [k,k] [k,k](叶子节点),它维护的值是在当前计算的位置的合法区间 [ m a x ( i − r , 0 ) , m a x ( i − l , 0 ) ] [max(i-r,0),max(i-l,0)] [max(ir,0),max(il,0)]内, s u m sum sum值为 k k k的数的 f f f最大是多少
这样我们只要动态地维护权值线段树就可以了,而每当 i i i往后移一次,实质上有效区间就是整体往后移了一位,要维护的就只有区间两端的数字,用优先队列维护 s u m sum sum的最大 f f f值即可
代码

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年06月22日 星期六 08时06分50秒
*******************************/
#include <cstdio>
#include <fstream>
#include <cstring>
#include <algorithm>
#include <queue>
#define mk make_pair
using namespace std;
const int maxn = 1000006;
const int m = 1000001;
const int inf = 10000007;
const char no [] = "Impossible";
//{{{cin 读入优化
struct IO{
	template<typename T>
	IO & operator>>(T&res){
		res=0;
		bool flag=false;
		char ch;
		while((ch=getchar())>'9'||ch<'0')	 flag|=ch=='-';
		while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
		if (flag)	 res=~res+1;
		return *this;
	}
}cin;
//}}}
int n,l,r;
int sum[maxn],f[maxn];
int val[maxn<<3],pos[maxn<<1],lt[maxn<<3],rt[maxn<<3];
priority_queue < pair<int,int> > q[maxn<<1];
//{{{build(k,l,r)
void build (int k,int l,int r)
{
	lt[k]=l,rt[k]=r;
	if (l==r){
		val[k]=-inf,pos[l]=k;
		return ;
	}
	int mid=(l+r)>>1;
	build (k<<1,l,mid);
	build (k<<1|1,mid+1,r);
	val[k]=max(val[k<<1],val[k<<1|1]);
}
//}}}
//{{{insert(u,v)
void insert (int u,int v)
{
	int k=pos[u];
	while (k){
		val[k]=max(val[k],v);
		k>>=1;
	}
}
//}}}
//{{{change(u,v)
void change (int u,int v)
{
	int k=pos[u];
	val[k]=v;
	while (k>>=1)	val[k]=max(val[k<<1],val[k<<1|1]);
}
//}}}
//{{{query(k,l,r)
int query (int k,int l,int r)
{
	if (lt[k]>=l&&rt[k]<=r)	return val[k];
	if (lt[k]>r||rt[k]<l)	return -inf;
	int res=-inf;
	res=max(res,query(k<<1,l,r));
	res=max(res,query(k<<1|1,l,r));
	return res;
}
//}}}
int main()
{
	cin>>n>>l>>r;
	for (int i=1;i<=n;++i)	cin>>sum[i],sum[i]+=sum[i-1];
	build(1,1,m<<1);
	for (int i=1;i<=n;++i)	f[i]=-inf;
	f[0]=0,q[0].push(mk(0,0));//二元组(f,k)表示f值和位置
	for (int i=l;i<=n;++i){
		int s=sum[i-l]+m;//防止负数
		insert(s,f[i-l]);
		q[s].push(mk(f[i-l],i-l));
		if (i>r){
			s=sum[i-r-1]+m;
			while (!q[s].empty()&&i-r>q[s].top().second)	q[s].pop();
			if(q[s].empty())	change(s,-inf);
			else	change(s,q[s].top().first);
		}
		s=sum[i]+m;
		f[i]=max(f[i],query(1,1,s-1)+1);
		f[i]=max(f[i],query(1,s,s));
		f[i]=max(f[i],query(1,s+1,m<<1)-1);
	}
	if (f[n]<-n)	printf("%s\n",no);
	else	printf("%d\n",f[n]);
	return 0;
}


<think> 我们被要求搜索关于"dis选举"的信息。根据问题描述,用户意图是了解"dis选举"的相关内容。 首先,我们需要明确"dis选举"是什么。通过快速搜索得知,"dis选举"可能指的是分布式一致性算法中的领导者选举(Leader Election)过程,特别是在分布式系统(Distributed Systems)中。 然而,考虑到用户可能指的是具体的算法或技术,我们将重点放在分布式系统中的领导者选举上。 分布式系统中的领导者选举是确保多个节点中选出一个领导者来协调任务的过程。常见的算法有Paxos、Raft、Zab等。 由于用户问题比较宽泛,我们将提供分布式领导者选举的基本概念、常见算法以及一个简单示例。 注意:我们要避免第一人称,避免步骤词汇(如首先、然后),将答案组织为多个方法或步骤,并在每个步骤间换行。 同时,我们需要在最后添加相关问题部分。 以下是回答的结构: 1. 分布式领导者选举概述 2. 常见的选举算法 3. 一个简单的选举算法示例(Bully算法) 我们将按照要求生成回答,并在最后添加相关问题。 </think> ### 分布式系统领导者选举(DIS选举)概述 分布式系统中的领导者选举(常称DIS选举)是确保集群节点协调一致的核心机制,通过算法选出一个主节点(Leader)负责决策和任务分配。以下为关键内容: --- #### 核心算法原理 **基础目标**:解决节点故障、网络分区下的主节点唯一性问题 **常用算法**: - **Bully算法**:高ID节点发起选举,强制低ID节点退出 - **Raft算法**:通过心跳机制和随机超时实现,分为**Leader选举**、**日志复制**两阶段 - 选举公式:节点超时时间 $T = T_{\text{base}} + \text{random}(0, T_{\text{range}})$ **ZooKeeper的Zab协议**: 使用epoch编号($E_{\text{new}} = E_{\text{current}} + 1$)确保事务顺序,选举过程依赖**zxid**(事务ID)优先级 --- #### 典型应用场景 1. **数据库集群**(如Redis Sentinel、MongoDB副本集) - 主节点故障时从节点发起投票 2. **微服务协调**(如Consul、Etcd) - 服务注册中心通过租约(Lease)机制维持领导者状态 3. **流处理系统**(如Apache Kafka Controller) - 分区Leader管理消息路由 --- #### 选举流程示例(Raft算法) ```python class RaftNode: def __init__(self, node_id): self.id = node_id self.state = "FOLLOWER" self.current_term = 0 def start_election(self): if self.state == "CANDIDATE": # 发送RequestVote RPC给其他节点 votes_received = self.request_votes() if votes_received > len(nodes) // 2: self.become_leader() def become_leader(self): self.state = "LEADER" # 定期发送心跳维持权威 self.send_heartbeat() ``` --- #### 挑战与优化 - **脑裂问题**:通过**Quorum机制**(多数节点确认)避免 - **性能优化**: - 预投票阶段(Pre-Vote)减少无效选举 - 心跳广播压缩(如gRPC streaming)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值