求卡常
  • 板块学术版
  • 楼主Harry27182SDream
  • 当前回复15
  • 已保存回复15
  • 发布时间2023/8/6 16:01
  • 上次更新2023/11/3 05:34:41
查看原帖
求卡常
376997
Harry27182SDream楼主2023/8/6 16:01

模拟赛被卡常了,n=3e5,1s,目前是 1.2s 左右,求卡进 1s,悬赏一关注。

大概就是一个 ODT ,一个线段树+单调栈的东西。

#pragma GCC optimize("O3,unroll-loops,fast-math,no-stack-protector")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include<bits/stdc++.h>
using namespace std;
struct node{int l,r,p;};set<node>s;
struct tree{int mn,tag;}tr[1200005];
struct point{int r,v;}st1[300005],st2[300005];
int n,d,a[300005],top1,top2,ans,x,y,v;
bool operator <(node x,node y){return x.l<y.l;}
auto split(int x)
{
	auto it=s.lower_bound(node{x,0,0});
	if(it!=s.end()&&it->l==x)return it;
	it--;int l=it->l,r=it->r,p=it->p;
	s.erase(it);
	s.insert(node{l,x-1,p});
	s.insert(node{x,r,p});
	return ++it;
}
void pushup(int k){tr[k].mn=min(tr[k<<1].mn,tr[k<<1|1].mn);}
void update(int k,int v){tr[k].mn+=v;tr[k].tag+=v;}
void pushdown(int k)
{
	if(!tr[k].tag)return;
	update(k<<1,tr[k].tag);update(k<<1|1,tr[k].tag);
	tr[k].tag=0;
}
void change(int k,int l,int r)
{
	if(x<=l&&r<=y){update(k,v);return;}
	int mid=(l+r)>>1;pushdown(k);
	if(x<=mid)change(k<<1,l,mid);
	if(y>mid)change(k<<1|1,mid+1,r);
	pushup(k);
}
int find(int k,int l,int r)
{
	if(tr[k].mn>0)return 0x3f3f3f3f;
	if(l==r)return l;
	int mid=(l+r)>>1;pushdown(k);
	if(tr[k<<1].mn==0)return find(k<<1,l,mid);
	else return find(k<<1|1,mid+1,r);
}
int read()
{
	int x=0;char s=getchar();
	while(s<'0'||s>'9')s=getchar();
	while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
	return x;
}
int main()
{
	n=read();d=read();
	for(int i=1;i<=n;i++)a[i]=read();
	s.insert(node{0,2000000000,0});x=1;y=n;v=1;change(1,1,n);
	for(int i=1;i<=n;i++)
	{
		int l=max(0,a[i]-(d-1)/2),r=a[i]+d/2;
		while(top1&&st1[top1].v>l)x=st1[top1-1].r+1,y=st1[top1].r,v=st1[top1].v,change(1,1,n),top1--;
		x=st1[top1].r+1;y=i;v=-l;change(1,1,n);st1[++top1]={i,l};
		while(top2&&st2[top2].v<r)x=st2[top2-1].r+1,y=st2[top2].r,v=-st2[top2].v,change(1,1,n),top2--;
		x=st2[top2].r+1;y=i;v=r;change(1,1,n);st2[++top2]={i,r};
		auto itr=split(r+1),itl=split(l);
		for(auto it=itl;it!=itr;it++)
		{
			x=it->p+1;y=i;v=-(it->r-it->l+1);
			change(1,1,n);
		}
		s.erase(itl,itr);s.insert(node{l,r,i});
		int p=find(1,1,n);
		if(p<=i)ans=max(ans,i-p+1);
	}
	printf("%d",ans);
	return 0;
}
2023/8/6 16:01
加载中...