题解:P10764 [BalticOI 2024] Wall

题面


美妙模拟赛拉原题。

给一个码量大点但是无脑的思路。


容易发现答案是 \(\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^n\min(pre_i,nxt_i)-h_i\),其中 \(pre_i,nxt_i\) 分别为 \(i\) 的前/后缀最大值。

因为 \(\min(pre_i,nxt_i)=pre_i+nxt_i-\max(pre_i,nxt_i)=pre_i+nxt_i-maxn\),所以原式又等于 \((\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^npre_i)+(\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^nnxt_i)-(\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^nmaxn)-(\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^nh_i)\)

我们考虑分开算这四个东西:

  • \((\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^nh_i)\) 在读入时处理,不讲。

  • \((n\sum\limits_{\forall h\{n\}}maxn)\) 考虑求 \(\sum\limits_{i=1}^{\inf}\sum\limits_{\forall h\{n\}}[i\le maxn]\)。具体地,我们考虑每个位置有多少选择是小于 \(i\) 的,全部乘起来容斥掉即可。

  • \((\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^npre_i),(\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^nnxt_i)\) 这两个等价,沿用上面的思路,我们考虑求 \(\sum\limits_{i=1}^{\inf}\sum\limits_{\forall h\{n\}}\sum\limits_{i=1}^n[i\le pre_i]\),我们设 \(f_{i,0/1}\) 表示长度为 \(i\) 的前缀最大值是否不小于 \(i\) 的方案数最终的数量就是 \(\sum\limits_{i=1}^nf_{i,1}\times 2^{n-i}\),我们考虑一个位置 \(x\)

    • 如果 \(a_x,b_x\) 都小于 \(i\),有 \(\begin{cases}f_{i,0}=2f_{i-1,0}\\f_{i,1}=2f_{i-1,1}\end{cases}\)
    • 如果 \(a_x,b_x\) 只有一个小于 \(i\),有 \(\begin{cases}f_{i,0}=f_{i-1,0}\\f_{i,1}=f_{i-1,0}+2f_{i-1,1}\end{cases}\)
    • 如果 \(a_x,b_x\) 都不小于 \(i\),有 \(\begin{cases}f_{i,0}=0\\f_{i,1}=2f_{i-1,0}+2f_{i-1,1}\end{cases}\)

容易发现这个可以用线段树维护转移矩阵实现。


恶臭的代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
char buf[1000005],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
int read(){
	int x=0,f=0,c=gc();
	while(!isdigit(c))f|=(c=='-'),c=gc();
	while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=gc();
	return f?-x:x;
}
const int mod=1e9+7;
int n,a[500005],b[500005];
struct node{
	int x,id;
	bool operator<(const node &t)const{return x<t.x;}
}x[1000005];
namespace Sol1{//算maxn
	struct ST{
		struct Node{
			int l,r,val;
		}c[2000005];
		void Build(int q,int l,int r){
			c[q].l=l;c[q].r=r;
			if(l==r){
				c[q].val=0;
				return;
			}
			int mid=l+r>>1;
			Build(q<<1,l,mid);
			Build(q<<1|1,mid+1,r);
			c[q].val=c[q<<1].val*c[q<<1|1].val%mod;
		}
		void Change(int q,int x,int y){
			if(c[q].l==c[q].r){
				c[q].val+=y;
				return;
			}
			int mid=c[q].l+c[q].r>>1;
			if(x<=mid)Change(q<<1,x,y);
			else Change(q<<1|1,x,y);
			c[q].val=c[q<<1].val*c[q<<1|1].val%mod;
		}
	}T;
	int main(){
		int tot=0;
		for(int i=1;i<=n;i++)x[++tot]=node({a[i],i}),x[++tot]=node({b[i],i});
		sort(x+1,x+tot+1);
		int Pow=1;
		for(int i=1;i<=n;i++)Pow=Pow*2%mod;
		int res=0;
		int las=0;
		T.Build(1,1,n);
		for(int i=1;i<=tot;i++){
			res=(res+(x[i].x-las+mod)%mod*(Pow-T.c[1].val+mod)%mod)%mod;
			T.Change(1,x[i].id,1);
			las=x[i].x;
		}
		return res;
	}
}
namespace Sol2{//算前缀
	struct M{
		int a[2][2];
		M(int op=0){
			a[0][0]=a[1][1]=op;
			a[1][0]=a[0][1]=0;
		}
		M operator+(const M &t)const{
			M res;
			res.a[0][0]=(a[0][0]+t.a[0][0])%mod;
			res.a[0][1]=(a[0][1]+t.a[0][1])%mod;
			res.a[1][0]=(a[1][0]+t.a[1][0])%mod;
			res.a[1][1]=(a[1][1]+t.a[1][1])%mod;
			return res;
		}
		M operator*(const M &t)const{
			M res;
			res.a[0][0]=(a[0][0]*t.a[0][0]+a[0][1]*t.a[1][0])%mod;
			res.a[0][1]=(a[0][0]*t.a[0][1]+a[0][1]*t.a[1][1])%mod;
			res.a[1][0]=(a[1][0]*t.a[0][0]+a[1][1]*t.a[1][0])%mod;
			res.a[1][1]=(a[1][0]*t.a[0][1]+a[1][1]*t.a[1][1])%mod;
			return res;
		}
		M operator*(const int &x)const{
			M res;
			res.a[0][0]=a[0][0]*x%mod;
			res.a[0][1]=a[0][1]*x%mod;
			res.a[1][0]=a[1][0]*x%mod;
			res.a[1][1]=a[1][1]*x%mod;
			return res;
		}
	}A0,A1,A2;
	int Pow[500005];
	struct ST{
		struct Node{
			int l,r;
			M val,sum;
		}c[2000005];
		void up(int q){
			int mid=c[q].l+c[q].r>>1;
			c[q].val=c[q<<1].val*c[q<<1|1].val;
			c[q].sum=(c[q<<1].sum*Pow[c[q].r-mid])+(c[q<<1].val*c[q<<1|1].sum);
		}
		void Build(int q,int l,int r){
			c[q].l=l;c[q].r=r;
			if(l==r){
				c[q].val=c[q].sum=A2;
				return;
			}
			int mid=c[q].l+c[q].r>>1;
			Build(q<<1,l,mid);
			Build(q<<1|1,mid+1,r);
			up(q);
		}
		void Change(int q,int x,const M &y){
			if(c[q].l==c[q].r){
				c[q].val=c[q].sum=y;
				return;
			}
			int mid=c[q].l+c[q].r>>1;
			if(x<=mid)Change(q<<1,x,y);
			else Change(q<<1|1,x,y);
			up(q);
		}
	}T;
	int sss[500005];
	int main(){
		A0.a[0][0]=2;A0.a[0][1]=0;
		A0.a[1][0]=0;A0.a[1][1]=2;
		
		A1.a[0][0]=1;A1.a[0][1]=1;
		A1.a[1][0]=0;A1.a[1][1]=2;
		
		A2.a[0][0]=0;A2.a[0][1]=2;
		A2.a[1][0]=0;A2.a[1][1]=2;
		Pow[0]=1;
		for(int i=1;i<=n;i++)Pow[i]=Pow[i-1]*2%mod,sss[i]=2;
		int tot=0,res=0;
		for(int i=1;i<=n;i++)x[++tot]=node({a[i],i}),x[++tot]=node({b[i],i});
		sort(x+1,x+tot+1);
		T.Build(1,1,n);
		for(int i=1;i<=tot;i++){
			res=(res+(x[i].x-x[i-1].x)%mod*T.c[1].sum.a[0][1]%mod)%mod;
			sss[x[i].id]--;
			if(sss[x[i].id]==1)T.Change(1,x[i].id,A1);
			else T.Change(1,x[i].id,A0);
		}
		return res;
	}
}
signed main()
{
	n=read();
	int sum=0;
	for(int i=1;i<=n;i++)a[i]=read(),sum=(sum+a[i])%mod;
	for(int i=1;i<=n;i++)b[i]=read(),sum=(sum+b[i])%mod;
	for(int i=1;i<n;i++)sum=sum*2%mod;
	int sss=Sol1::main()*n%mod;
	int ss=Sol2::main();
	for(int i=1;i+i<=n;i++)swap(a[i],a[n-i+1]),swap(b[i],b[n-i+1]);
	ss=(ss+Sol2::main());
	printf("%lld",(ss-sum-sss+mod+mod)%mod);
	return 0;
}
posted @ 2024-12-03 19:55  Grisses  阅读(11)  评论(0)    收藏  举报
Document