求该做法的时间复杂度和证明
查看原帖
求该做法的时间复杂度和证明
187232
Logic_J_X楼主2023/11/8 19:14

思路

考虑在分治时处理跨越分治中心 midmid 的区间的贡献。

为了不计重,先枚举 ll 计数最小值在 [l,mid][l,mid] 时有贡献的 rr,然后再枚举 rr 计数最小值在 (mid,r](mid,r] 时有贡献的 ll 。处理最小值同时在[l,mid][l,mid] 和 (mid,r](mid,r] 的情况,则在值相等时钦定在 [l,mid][l,mid] 内的值更小即可。

考虑如何计数最小值在 [l,mid][l,mid] 时有贡献的 rr(枚举 rr 时类似)。

设当前的分治区间为 [L,R][L,R] , mnlimnl_i 表示 下标在 [i,mid][i,mid] 的 BB 的最小值,mnrimnr_i 表示 下标在 (mid,i](mid,i] 的 BB 的最小值,sis_i 表示 下标在 [1,i][1,i] 的 AA 的和。

则最小值在 [l,mid][l,mid] 时对于 l∈[L,mid]l\in[L,mid] ,一个右端点 r∈(mid,r]r\in(mid,r] 有贡献,当且仅当:mnll≤mnrrmnl_l\leq mnr_r 且 sr−sl−1+mnll≤Ss_r-s_{l-1}+mnl_l\leq S。

显然有贡献的右端点 rr 是一个以 mid+1mid+1 为起点的前缀,用一个指针 eded 动态维护。

目前最优解,但本人水平有限,无法准确求出其时间复杂度和给出证明。

代码

#include<bits/stdc++.h>
#define LL unsigned long long
#define int LL
#define ci const int
#define pb push_back 
#define II inline int 
#define IV inline void
#define lb lower_bound
#define re read() 
#define pf printf

#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define mt(a,b) memset(a,b,sizeof(a)) 
#define clr(a,n) memset(a,0,sizeof(int)*(n)) 
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
#define f(i,x,y) for(int i=(x); i<=(y); ++i)
#define fl(i,x,y) for(int i=(x); i<(y); ++i)
#define fb(i,x,y) for(int i=(y); i>=(x); --i)
#define fe(i,v,u) for(int i=head[u],v=e[i].v; i; i=e[i].nex,v=e[i].v)
using namespace std;
#define TIM (to_string((double)(clock()-TST) / CLOCKS_PER_SEC)+" Sec")
#define MEM (to_string(fabs((&MST)-(&MED))/1024.0/1024.0)+" MiB")
const clock_t TST=clock();
bool MST;
#define edl cout<<"\n"
inline namespace Debug{
  template<typename ...Args>IV err(Args ...args){
    for(auto x:{args...}) cout<<x<<" "; cout<<"\n";
  }
  IV err_prefix(string func,int line,string args){
    cout<<" | "<<func<<" : "<<line<<" - "<<"["<<args<<"] = ";
  }
  #define deb(args...) err_prefix(__FUNCTION__,__LINE__,#args),err(args)
}
ci N=200005;
char buf[1<<21],*p1=buf,*p2=buf;
#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
II read(){
	int res=0; char c=gc;
	while(c<'0'||'9'<c) c=gc;
	while('0'<=c&&c<='9') res=(res<<1)+(res<<3)+(c^48),c=gc;
	return res;
} 
int n,mx,a[N],b[N],s[N];
LL ans;
int mn[N],c[N];
IV calc(ci l,ci r){
	if(l==r) return ;
	ci mid=l+r>>1;
	calc(l,mid); calc(mid+1,r);
	mn[mid]=a[mid]; mn[mid+1]=a[mid+1];
	fb(i,l,mid-1) mn[i]=min(mn[i+1],a[i]);
	f(i,mid+2,r) mn[i]=min(mn[i-1],a[i]);
//deb(l,mid,mid+1,r);
	int ed;
	ed=r;
	fb(i,l,mid){
		while(mid<ed && (s[ed]-s[i-1]+mn[i]>mx || mn[ed]<mn[i])) ed--;
		while(ed<r && (s[ed+1]-s[i-1]+mn[i]<=mx && mn[ed+1]>=mn[i])) ed++;
//deb(i,ed,mid,ed-mid);
//deb(s[ed]-s[i-1]+mn[i]);
		ans+=ed-mid;
	}
//deb(ans);
	ed=l;
	f(i,mid+1,r){
		while(ed<=mid && (s[i]-s[ed-1]+mn[i]>mx || mn[ed]<=mn[i])) ed++;
		while(l<ed && (s[i]-s[ed-2]+mn[i]<=mx && mn[ed-1]>mn[i])) ed--;
//deb(i,mid,ed,mid-ed+1);
//deb(s[i]-s[ed-1]+mn[i]);
		ans+=mid-ed+1;
	}
//edl;
//deb(ans); 
//edl; edl;
}
signed main(){
//	freopen("in.cpp","r",stdin);
	n=re; mx=re;
	f(i,1,n) a[i]=re;
	f(i,1,n) b[i]=re,s[i]=s[i-1]+b[i],ans+=(a[i]+b[i]<=mx);
//deb(ans);
	calc(1,n);
	pf("%llu",ans);
	return 0;
}
2023/11/8 19:14
加载中...