1. 程式人生 > >【題解】[牛客網NOIP賽前集訓營-提高組(第二場)]B.分糖果 單調棧優化線性DP+容斥原理

【題解】[牛客網NOIP賽前集訓營-提高組(第二場)]B.分糖果 單調棧優化線性DP+容斥原理

題目連結
在這裡插入圖片描述
在這裡插入圖片描述


在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include<cstdio>
#define re register
typedef long long ll;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
template<typename tp>inline int getmin(tp&x,tp y){return y<x?x=y,1:0;}
template<typename tp>inline int getmax(tp&x,tp y){return y>x?x=y,1:0;}
template<typename tp>inline void read(tp&x)
{
	x=0;re int f=0;re char ch=getchar();
	while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	if(f)x=-x;
}
template<typename tp>inline void write(tp x)
{
	re int buf[40],p=0;
	if(x<0)putchar('-'),x=-x;
	do{
		buf[p++]=x%10;x/=10;
	}while(x);
	for(re int i=p-1;i+1;i--)putchar(buf[i]+48);
	putchar('\n');
}
template<typename tp>inline int add(tp x,tp y){return x+y>=mod?x+y-mod:x+y;}
template<typename tp>inline int dec(tp x,tp y){return x-y<0?x-y+mod:x-y;}
template<typename tp>inline int mul(tp x,tp y){return 1ll*x*y%mod;}
int n,mn=INF,a[N],pos,b[N],sta[N],val[N],f[N],sum,top;
int main()
{
	//freopen("in.txt","r",stdin);
    read(n);
    for(re int i=1;i<=n;i++)
    {
    	read(a[i]);
    	if(getmin(mn,a[i]))pos=i;
	}
	for(re int i=1;i<=n;i++)
	    b[i]=a[(pos+i-2)%n+1];
	sta[++top]=1;val[1]=b[1];f[1]=b[1];
	for(re int i=2;i<=n;i++)
	{
		sta[++top]=i;val[i]=f[i-1];
		while(top>1&&b[sta[top-1]]>b[sta[top]])
		{
			if((i-sta[top-1])&1)
			{
				val[i]=dec(val[i],val[sta[top-1]]);
				sum=dec(sum,mul(b[sta[top-1]],val[sta[top-1]]));
			}
			else
			{
				val[i]=add(val[i],val[sta[top-1]]);
				sum=add(sum,mul(b[sta[top-1]],val[sta[top-1]]));
			}
			sta[top-1]=sta[top];top--;
		}
		sum=dec(mul(b[i],val[i]),sum);
		if(i&1)f[i]=add(sum,f[1]);
		else f[i]=dec(sum,f[1]);
	}
	for(re int i=top;i>1;i--)
	{
		if((n-sta[i])&1)f[n]=add(f[n],val[sta[i]]);
		else f[n]=dec(f[n],val[sta[i]]);
	}
	f[n]=(n&1?dec(f[n],f[1]):add(f[n],f[1]));
	write(f[n]);return 0;
}

總結

容斥原理結合單調棧DP好題