「JOI 2021 Final」地牢 3


「JOI 2021 Final」地牢 3

判定無解

無解即:\(\exists i\in[S,T-1],A_i>U\)

是一個簡單的區間最值問題

\[\ \]

\(O(nm)\)

關於用單調隊列之類的東西維護每個點權值的方法這里就不提了

形式化地,我們把一層層點放到數軸上,令\(X_i=\sum_{j<i}A_j\)

在數軸上坐標每\(+1\)消耗一點能量,我們要從\(X_S\)走到\(X_T\)

考慮每個點的情況,不妨看做是用\(B_i\)去覆蓋\((X_S,X_T]\),求最小權值

發現對於\(B_i\),它能夠合法覆蓋的區間一定是\((X_i,X_i+U]\)

暴力地,可以直接讓\(B_i\)更新這段區間的最小權值,然后暴力求和

\[\ \]

進一步分析每個\(B_i\)覆蓋的區間,可以發現是合法區間\((X_i,X_i+U]\)中的某一連續段\((L_i,R_i]\)

\(L_i\)取決於\(B_i\)前面第一個\(B_{pre}<B_i\)\(R_i\)取決於后面第一個\(B_{nxt}\leq B_i\)

關於\(pre,nxt\)的求解顯然只是一個單調棧解決

得到\((L_i,R_i]\)簡單的描述

\(L_i=\max\{X_i,X_{pre}+U\}\)

\(R_i=\min\{X_i+U,X_{nxt}\}\)

(ps:這樣求得的\(L_i\)不一定\(<R_i\))

暴力枚舉即可\(O(n)\)查詢

\[\ \]

\[\ \]

\(T_i=n+1\) 從這里開始需要一些數據結構?

考慮倒着從\(n\)\(1\)計算每一個\(S_i\)的答案

發現在剛插入\(i\)的時候,\(pre_i\)還未出現,可以看做\(-\infty\)\(nxt_i\)已經確定

\(pre_i\)出現時可以重新進行一次插入

每次插入可以用三元組表示\((i,pre,nxt)\),為了便於敘述這里\(pre,nxt\)直接是坐標

考慮對於\(L_i,R_i\)進行參數分離計算,首先要考慮何時滿足\(L_i<R_i\)

顯然條件就是\(nxt-pre>U\)

\(\displaystyle L_i=\max\{X_i,X_{pre}+U\}=X_{pre}+\max\{X_i-X_{pre},U\}\)

\(\displaystyle R_i=\min\{X_i+U,X_{nxt}\}=X_i+\min\{U,X_{nxt}-X_i\}\)

\(\displaystyle Answer=\sum_{nxt-pre>U} (R_i-L_i)\cdot B_i\)

離線詢問,離散之后可以用樹狀數組維護上述式子,對於不合法部分不要加入即可

\[\ \]

\[\ \]

\(O(n\log n)\)

上面已經能計算\(T_i=n+1\)的詢問,考慮將\(S,T\)轉化為\(T_{i}=n+1\)的問題

如果直接\(S,T\)相減顯然不合法,不妨找到在\((S,n+1)\)的方案中,覆蓋的\(T\)的點\(T'\)

\((S,n+1)-(T',n+1)\)會抵消掉在\(S\)的方案中\(T\)右邊的部分,而\((X_{T'},X_T]\)顯然仍然是由\(B_{T'}\)覆蓋,補回來即可

由此完成分離操作,而根據上面區間覆蓋的定義,\(T'\)實際上就是\((X_T-U,X_T]\)中最小的\(B_i\)

所有操作都可以\(O(n\log n)\)完成

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair <int,int> Pii;
#define mp make_pair
#define pb push_back
#define Mod1(x) ((x>=P)&&(x-=P))
#define Mod2(x) ((x<0)&&(x+=P))
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }

char IO;
int rd(){
	int s=0,f=0;
	while(!isdigit(IO=getchar())) f|=IO=='-';
	do s=(s<<1)+(s<<3)+(IO^'0');
	while(isdigit(IO=getchar()));
	return f?-s:s;
}

const int N=2e5+10,INF=1e9+10;

int n,m,A[N],B[N],nxt[N],stk[N],top,C;
ll ans[N],X[N],H[N];
struct Node{ int U,k,id; };
vector <Node> Q[N];
vector <int> G[N];
struct BIT{
	ll s[N];
	void Add(int p,ll x){ 
		while(p<=C) s[p]+=x,p+=p&-p; 
	}
	ll Que(int p){
		ll res=0;
		while(p) res+=s[p],p-=p&-p;
		return res;
	}
} T1,T2;
// T1維護式子中含U項的和
// T2維護式子中常數和

struct MaxTree{
	int s[N<<2],bit;
	void Build(){
		for(bit=1;bit<=n+1;bit<<=1) ;
		rep(i,1,n) s[bit+i]=A[i];
		drep(i,bit,1) s[i]=max(s[i<<1],s[i<<1|1]);
	}
	int Que(int l,int r){
		if(l==r) return s[l+bit];
		int res=0;
		for(l+=bit-1,r+=bit+1;l^r^1;l>>=1,r>>=1){
			if(~l&1) cmax(res,s[l^1]);
			if(r&1) cmax(res,s[r^1]);
		}
		return res;
	}
} Max;
struct MinTree{
	int s[N<<2],bit;
	int Min(int x,int y){ return mp(B[x],x)<mp(B[y],y)?x:y; }
	void Build(){
		B[0]=1e9;
		for(bit=1;bit<=n+1;bit<<=1) ;
		rep(i,1,n) s[bit+i]=i;
		drep(i,bit,1) s[i]=Min(s[i<<1],s[i<<1|1]);
	}
	int Que(int l,int r){
		if(l==r) return s[l+bit];
		int res=0;
		for(l+=bit-1,r+=bit+1;l^r^1;l>>=1,r>>=1){
			if(~l&1) res=Min(res,s[l^1]);
			if(r&1) res=Min(res,s[r^1]);
		}
		return res;
	}
} Min;
// Min 用於尋找T'

void Add(int i,ll pre,ll nxt,int k){
	int p=lower_bound(H+1,H+C+1,X[i]-pre)-H,r=lower_bound(H+1,H+C+1,nxt-pre)-H;
	// -L
	T1.Add(p,-B[i]*k), T1.Add(r,B[i]*k);
	T2.Add(p,k*B[i]*(X[i]-pre)), T2.Add(r,-k*B[i]*(X[i]-pre));
	// +R 
	p=lower_bound(H+1,H+C+1,nxt-X[i])-H;
	T1.Add(1,k*B[i]),T1.Add(p,-k*B[i]);
	T2.Add(p,k*(nxt-X[i])*B[i]),T2.Add(r,-k*(nxt-X[i])*B[i]);
}

int main(){
	n=rd(),m=rd();
	rep(i,1,n) A[i]=rd(),X[i+1]=X[i]+A[i];
	rep(i,1,n) B[i]=rd();
	drep(i,n+1,1) {
		while(top && B[stk[top]]>=B[i]) G[i].pb(stk[top--]);
		nxt[i]=stk[top],stk[++top]=i;
	}
	Min.Build(),Max.Build();
	rep(i,1,m) {
		int S=rd(),T=rd(),U=rd();
		if(Max.Que(S,T-1)>U){ ans[i]=-1; continue; }
		H[++C]=U,Q[S].pb((Node){U,1,i});
		int l=lower_bound(X+1,X+n+2,X[T]-U)-X; cmax(l,S);
		int t=Min.Que(l,T);
		ans[i]+=(X[T]-X[t])*B[t];
		Q[t].pb((Node){U,-1,i});
	}
	sort(H+1,H+C+1),C=unique(H+1,H+C+1)-H-1;
	drep(i,n,1){
		Add(i,-1e9,X[nxt[i]],1);
		for(int j:G[i]) Add(j,-1e9,X[nxt[j]],-1),Add(j,X[i],X[nxt[j]],1);
		for(Node j:Q[i]){
			int p=lower_bound(H+1,H+C+1,j.U)-H;
			ans[j.id]+=j.k*(j.U*T1.Que(p)+T2.Que(p));
		}
	}
	rep(i,1,m) printf("%lld\n",ans[i]);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM