ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LOJ #3634. 「2021 集训队互测」音符大师

2022-03-29 08:32:59  阅读:271  来源: 互联网

标签:Ns LOJ 3634 int M1 2021 M2 now define


题面传送门
首先好像有一道题交闹钟来着,是\(m=0\)的版本。
考虑设\(f_{i,j,0/1}\)为一个点在\([a_i-m,a_i]\)左/右,另一个点在\(j\)点的最小答案。
然后转移分类讨论:首先找到第一个不在\([a_i-m,a_i]\)区间内的位置\(x\),如果找不到直接贡献答案。
如果是这一步转移\(a_i\),那么相当于全局加一个数,然后合并。
如果这一步转移\(j\),再分类讨论:
如果\(j\)不被\([a_x-m,a_x]\)包含,那么相当于区间查询值正负下标的最小值,然后单点修改。
如果\(j\)被包含,那么向后找到两个区间都不包含的一个最近位置,然后单点修改即可。
容易发现上述过程可以用线段树维护,时间复杂度\(O(nm\log n)\)
写代码的时候重构了一次,加上本来的压行,代码已经不能看了qwq
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N (50000+5)
#define M (2500000+5)
#define K (200000+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,k,x,y,z,A[N],Ns[N<<1],Nh,Id,L[N],R[N],Rs[N][2],Cnt,N1,N2,N3;ll Ans=1e18,Pus,G[60];
namespace TT{
	#define ls now<<1
	#define rs now<<1|1
	queue<int> F[N<<3];int Val[N<<3];I void Up(int now){Val[now]=min(Val[ls],Val[rs]);}
	I void Ins(int x,int y,int l=1,int r=Nh,int now=1){if(l==r) {F[now].push(y);Val[now]=F[now].front();return;}int m=l+r>>1;x<=m?Ins(x,y,l,m,ls):Ins(x,y,m+1,r,rs);Up(now);}
	I void Del(int x,int l=1,int r=Nh,int now=1){if(l==r){F[now].pop();Val[now]=(F[now].empty()?1e9:F[now].front());return;}int m=l+r>>1;x<=m?Del(x,l,m,ls):Del(x,m+1,r,rs);Up(now);}
	I void Qry(int x,int y,int &Ans,int l=1,int r=Nh,int now=1){if(x>y) return;if(Val[now]>=Ans) return;if(x<=l&&r<=y){Ans=Val[now];return;};int m=l+r>>1;x<=m&&(Qry(x,y,Ans,l,m,ls),0);y>m&&(Qry(x,y,Ans,m+1,r,rs),0);}
	#undef ls
	#undef rs
}
namespace Tree{
	ll M1[M*6],M2[M*6],Fl[M*6];int L[M*6],R[M*6],cnt,st[M*6],H;I void Up(int now){M1[now]=min(M1[L[now]],M1[R[now]]);M2[now]=min(M2[L[now]],M2[R[now]]);}
	I void PF(int now,ll w){now&&(Fl[now]+=w,M1[now]+=w,M2[now]+=w);}I void P(int now){Fl[now]&&(PF(L[now],Fl[now]),PF(R[now],Fl[now]),Fl[now]=0);}
	I void Ins(int x,ll y,int &now,int l=1,int r=Nh){/*Cnt++;*/!now&&(now=(H?st[H--]:++cnt),L[now]=R[now]=Fl[now]=0,M1[now]=M2[now]=1e18);if(l==r){/*printf("%d %lld\n",x,y);*/M1[now]=min(M1[now],y-Ns[l]);M2[now]=min(M2[now],y+Ns[l]);return;}P(now);int m=l+r>>1;x<=m?Ins(x,y,L[now],l,m):Ins(x,y,R[now],m+1,r);Up(now);}
	I ll Q1(int x,int y,int now,int l=1,int r=Nh){if(x<=l&&r<=y) return M1[now];int m=l+r>>1;ll F1=1e18,F2=1e18;P(now);x<=m&&(F1=Q1(x,y,L[now],l,m));y>m&&(F2=Q1(x,y,R[now],m+1,r));return min(F1,F2);}
	I ll Q2(int x,int y,int now,int l=1,int r=Nh){if(x<=l&&r<=y) return M2[now];int m=l+r>>1;ll F1=1e18,F2=1e18;P(now);x<=m&&(F1=Q2(x,y,L[now],l,m));y>m&&(F2=Q2(x,y,R[now],m+1,r));return min(F1,F2);}
	I int ME(int x,int y,int l=1,int r=Nh){if(!x||!y) return x|y;P(x);P(y);st[++H]=y;M1[x]=min(M1[x],M1[y]);M2[x]=min(M2[x],M2[y]);if(l==r)return x;int m=l+r>>1;L[x]=ME(L[x],L[y],l,m);R[x]=ME(R[x],R[y],m+1,r);/*Up(x);*/return x;}
	I void calc(int now,int l=1,int r=Nh){if(!now) return;st[++H]=now;if(l==r) {/*if(now) printf("%d %lld\n",l,min(M1[now]+Ns[l],M2[now]+Ns[l]));*/Ans=min(Ans,min(M1[now]+Ns[l],M2[now]-Ns[l]));return;}P(now);int m=l+r>>1;calc(L[now],l,m);calc(R[now],m+1,r);}
	I void NEW(int x,int &now,int l=1,int r=Nh){!now&&(now=(H?st[H--]:++cnt),L[now]=R[now]=Fl[now]=0,M1[now]=M2[now]=1e18);if(l==r) return;P(now);int m=l+r>>1;x<=m?NEW(x,L[now],l,m):NEW(x,R[now],m+1,r);Up(now);}
	I void Find(int x,int y,int now,int l=1,int r=Nh){if(!now)return;if(l==r){G[l-x+1]=M1[now]+Ns[l];return;}int m=l+r>>1;P(now);x<=m&&(Find(x,y,L[now],l,m),0);y>m&&(Find(x,y,R[now],m+1,r),0);}
//	I void Push(int x,int y,int z,int &now,int l=1,int r=Nh){!now&&(now=(H?st[H--]:++cnt),L[now]=R[now]=Fl[now]=0,M1[now]=M2[now]=1e18);if(l==r){M1[now]=min(M1[now],G[l-x+1][z]-Ns[l]);M2[now]=min(M2[now],G[l-x+1][z]+Ns[l]);return;}int m=l+r>>1;P(now);x<=m&&(Push(x,y,z,L[now],l,m),0);y>m&&(Push(x,y,z,R[now],m+1,r),0);Up(now);}
}
I int calc(int x,int y,int l,int r){/*Cnt-=clock();*/x>l&&(swap(x,l),swap(y,r),0);N1=N2=N3=1e9;TT::Qry(1,x-1,N1);TT::Qry(y+1,l-1,N2);TT::Qry(r+1,Nh,N3);/*Cnt+=clock();*/return min(N1,min(N2,N3));}
I void Solve(int X,int Y,int Ro){
	N1=N2=1e9;TT::Qry(1,X-1,N1);TT::Qry(Id?(Y+1):(UB(Ns+1,Ns+Nh+1,Ns[X]+m)-Ns),Nh,N2);x=min(N1,N2);/*if(!Id) cerr<<x<<'\n';*/assert(x>Id);if(x>n) {Tree::calc(Ro);return;}
	if(L[x]^1) /*cerr<<X<<' '<<Y<<' '<<Tree::Q1(1,L[x]-1,Ro)+Ns[L[x]]<<'\n',*/Tree::Ins(X,Tree::Q1(1,L[x]-1,Ro)+Ns[L[x]],Rs[x][0]);
	if(R[x]^Nh) Tree::Ins(X,Tree::Q2(R[x]+1,Nh,Ro)-Ns[R[x]],Rs[x][1]);
	Me(G,0x3f);Tree::Find(L[x],R[x],Ro);
	for(RI i=L[x];i<=R[x];i++){
		Pus=G[i-L[x]+1];if(Pus>1e17){/*Tree::NEW(i,Rs[y][0]);Tree::NEW(i,Rs[y][1]);Tree::NEW(X,Rs[y][0]);Tree::NEW(X,Rs[y][1]);*/continue;}y=calc(X,Y,i,UB(Ns+1,Ns+Nh+1,Ns[i]+m)-Ns-1);if(y>n){Ans=min(Ans,Pus);continue;}
		if(X<L[y]) /*assert(Ns[L[y]]-Ns[X]>0),*/Tree::Ins(i,Pus+Ns[L[y]]-Ns[X],Rs[y][0]);else /*assert(Ns[X]-Ns[R[y]]>0),*/Tree::Ins(i,Pus+Ns[X]-Ns[R[y]],Rs[y][1]);
		if(i<L[y]) /*assert(Ns[L[y]]-Ns[i]>0),*/Tree::Ins(X,Pus+Ns[L[y]]-Ns[i],Rs[y][0]);else /*assert(Ns[i]-Ns[R[y]]>0),*/Tree::Ins(X,Pus+Ns[i]-Ns[R[y]],Rs[y][1]);
	}
	if(X<L[x]) /*assert(Ns[L[x]]-Ns[X]>0),*/Tree::PF(Ro,Ns[L[x]]-Ns[X]),Rs[x][0]=Tree::ME(Rs[x][0],Ro);else /*cerr<<Id<<' '<<x<<' '<<X<<' '<<Y<<' '<<L[x]<<' '<<R[x]<<'\n',*//*assert(Ns[X]-Ns[R[x]]>0),*/Tree::PF(Ro,Ns[X]-Ns[R[x]]),Rs[x][1]=Tree::ME(Rs[x][1],Ro);
}
int main(){
	freopen("1.in","r",stdin);//freopen("1.out","w",stdout);
	RI i,j,h;Me(TT::Val,0x3f);Me(Tree::M1,0x3f);Me(Tree::M2,0x3f);scanf("%d%d",&n,&m);Ns[Nh=1]=0;for(i=1;i<=n;i++) {scanf("%d",&A[i]);Ns[++Nh]=A[i];Ns[++Nh]=A[i]-m;}sort(Ns+1,Ns+Nh+1);
	Nh=unique(Ns+1,Ns+Nh+1)-Ns-1;for(i=1;i<=n;i++) L[i]=LB(Ns+1,Ns+Nh+1,A[i]-m)-Ns,R[i]=LB(Ns+1,Ns+Nh+1,A[i])-Ns;L[0]=R[0]=LB(Ns+1,Ns+Nh+1,0)-Ns;
	for(i=0;i<=n;i++) TT::Ins(R[i],i);Tree::Ins(L[0],0,Rs[0][0]);for(i=0;i<=n;i++){//printf("%d\n",i);
		Id=i;TT::Del(R[i]);Solve(L[i],R[i],Rs[i][0]);Solve(R[i],UB(Ns+1,Ns+Nh+1,Ns[R[i]]+m)-Ns-1,Rs[i][1]);
//		
//		for(j=L[i-1];j<=R[i-1];j++){
//			if(j>=L[i]&&j<=R[i]) {R2[j-L[i]+1]=Tree::ME(R2[j-L[i]+1],R1[j-L[i-1]+1]);continue;}
//			Tree::Find(L[i],R[i],j-L[i-1]+1,R1[j-L[i-1]+1]);
//			//for(h=L[i];h<=R[i];h++) Tree::Ins(j,Tree::Q1(h,h,R1[j-L[i-1]+1])+Ns[h],R2[h-L[i]+1]);
//			if(L[i]^1) Tree::Ins(j,Tree::Q1(1,L[i]-1,R1[j-L[i-1]+1])+Ns[L[i]],R2[1]);
//			if(R[i]^Nh) Tree::Ins(j,Tree::Q2(R[i]+1,Nh,R1[j-L[i-1]+1])-Ns[R[i]],R2[R[i]-L[i]+1]);
//			
//			if(j<L[i]) Tree::PF(R1[j-L[i-1]+1],Ns[L[i]]-Ns[j]),R2[1]=Tree::ME(R2[1],R1[j-L[i-1]+1]);
//			else Tree::PF(R1[j-L[i-1]+1],Ns[j]-Ns[R[i]]),R2[R[i]-L[i]+1]=Tree::ME(R2[R[i]-L[i]+1],R1[j-L[i-1]+1]);
//		}
//		for(j=L[i];j<=R[i];j++) Tree::Push(L[i-1],R[i-1],j-L[i]+1,R2[j-L[i]+1]);
	}
	//for(i=L[n];i<=R[n];i++) /*printf("%d\n",i-L[n]+1),*/Tree::calc(R2[i-L[n]+1]);
	printf("%lld\n",Ans);cerr<<Cnt<<'\n';
}
/*20 5
1 5 5 6 1 18 13 5 1 11 3 1 9 1 1 1 5 6 4 1 

20 5
1 20 9 20 9 4 6 1 8 13 6 19 13 9 5 5 16 9 5 8 
*/

标签:Ns,LOJ,3634,int,M1,2021,M2,now,define
来源: https://www.cnblogs.com/275307894a/p/16070063.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有