【ybtoj】【RMQ问题】与众不同

题意

【ybtoj】【RMQ问题】与众不同

题解

虽然在\(RMQ\)的章节里,但是这题的重点不在\(RMQ\),只是一个优化
考虑如何找到一段完美序列
记录\(lst[val]\)表示val值上次出现的位置,\(pre[i]\)表示以\(i\)为结尾的完美序列的起点
那么转移式很显然

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f,N = 2e5+10;
inline ll read()
{
	ll ret=0;char ch=' ',c=getchar();
	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
	return ch=='-'?-ret:ret;
}
int n,w[N],ecnt=-1,head[N],minw=INF,du[N];
ll ans;
struct edge
{
	int nxt,to;
}a[N<<1];
inline void add(int x,int y)
{
	a[++ecnt]=(edge){head[x],y};
	head[x]=ecnt;
}
void dfs(int u,int fa)
{
	if(!w[u]) return;
	minw=min(minw,w[u]);
	for(int i=head[u];~i;i=a[i].nxt)
	{
		int v=a[i].to;
		if(v==fa||!w[v]) continue;
		dfs(v,u);
		break;
	}
	w[u]-=minw;
	if(w[u]==0) 
		for(int i=head[u];~i;i=a[i].nxt)
		{
			int v=a[i].to;
			du[v]--;
		}
}
int main()
{
	freopen("snow.in","r",stdin);
	freopen("snow.out","w",stdout);
	memset(head,-1,sizeof(head));
	n=read();
	for(int i=1;i<=n;i++) w[i]=read();
	for(int i=1;i<n;i++)
	{
		int u=read(),v=read();
		add(u,v),add(v,u);
		du[u]++,du[v]++;
	}
	while(1)
	{
		//printf("1");
		minw=INF;
		bool flag=0;
		for(int i=1;i<=n;i++)
		{	
			if(w[i]&&du[i]<=1) 
			{
				flag=1,dfs(i,0),ans+=minw;
			//	printf("i=%d\n",i);
			
			//for(int i=1;i<=n;i++)
			//	printf("w[%d]=%d\n",i,w[i]);
			}
		}
	
		if(!flag) break;
	}
	printf("%lld",ans);
	return 0;
}
/*
5
5 4 5 3 2
1 2
2 3
3 4
3 5
*/
上一篇:[总结] 四毛子算法


下一篇:矿视界译文:Chia加入开放计算项目,助推存储循环经济