悬3关求调88ptsWA
查看原帖
悬3关求调88ptsWA
1076971
anke2017楼主2025/6/16 16:48

RT.

值域较小的巨大数据都能过的。而且不 TLE。剩下三个点就是过不了。

#include<bits/stdc++.h>
using namespace std;
#define inline __inline
constexpr int maxn=1e5+5;constexpr int maxm=1e5+5;
constexpr long long inf=1e16;
constexpr int siz=408;//有预感要大调 
//points
struct point
{
	long long x,y;
	inline point(long long xx=0,long long yy=0):x(xx),y(yy){}
	inline point operator +(point t){return point(x+t.x,y+t.y);}
	inline point operator -(point t){return point(x-t.x,y-t.y);}
};
typedef point Vector;
inline long long cross_mul(Vector x,Vector y){return x.x*y.y-x.y*y.x;}
//memory_pool
struct big_memory_pool
{
	point pool[131072];
	point* now;
	big_memory_pool(){now=pool;}
	__inline void del(point* st){now=st;}
	__inline point* get_area(int siz){static point* ans;ans=now;now+=siz;return ans;}
};
//convex_hull
struct multi_dot
{
	point* points;
	int cnt;
	int now;
	long long tag;
	multi_dot(){points=NULL,cnt=0,now=0,tag=0;}
	inline point operator [](const int &val){return points[val]+(point){0,points[val].x*tag};}
	inline void operator =(point* t){points=t;}
	inline void get_convex_hull()
	{
		if(cnt<=1)return;
		for(int i=0;i<=cnt;i++)
			if(points[i].y!=-inf)
				points[i].y+=points[i].x*tag;
		tag=0;
		int t=1;
		for(int i=2;i<=cnt;i++)
		{
			if(points[i].y==-inf)continue;
			while(t&&cross_mul(points[t]-points[t-1],points[i]-points[t-1])>=0)t--;
			points[++t]=points[i];
		}
		cnt=t;
		now=0;
	}
	inline void clear()
	{
		tag=0;
        now=0;
		points[0]={0,0};
		for(long long i=1;i<=cnt;i++)points[i]={i,-inf}; 
	}
	inline void insert(point t){points[t.x].y=max(points[t.x].y,t.y);}
	inline int size(){return cnt;}
	inline long long query(long long dx)
	{
		dx+=tag;
		while(now!=cnt&&(points[now].y+dx*points[now].x)<(points[now+1].y+dx*points[now+1].x))now++;
		return points[now].y+dx*points[now].x;
	}
	inline void pb(point t){points[++cnt]=t;}
	inline long long query_once(long long dx)
	{
		dx+=tag;
		int l=-1,r=cnt;
		while(l<r-1)
		{
			int mid=(l+r)>>1;
			if((points[mid].y+dx*points[mid].x)<(points[mid+1].y+dx*points[mid+1].x))l=mid;
			else r=mid;
		}
		return points[r].y+dx*points[r].x;
	}
};
//merge convex_hull
inline void merge(multi_dot &a,multi_dot &b,multi_dot &ans)
{
	int l=0,r=0;
	ans.insert(a[0]+b[0]);
	while(l<a.size()&&r<b.size()){ans.insert(cross_mul(a[l+1]-a[l],b[r+1]-b[r])>=0?a[l]+b[++r]:a[++l]+b[r]);}
	while(l<a.size())ans.insert(b[r]+a[++l]);
	while(r<b.size())ans.insert(a[l]+b[++r]);
}
//store ans
struct node
{
	long long ls,rs,mx,sum;
	inline node operator +(node tmp)
	{
		return (node){max(ls,sum+tmp.ls),max(tmp.rs,tmp.sum+rs),max(max(mx,tmp.mx),rs+tmp.ls),sum+tmp.sum};
	}
};
//node
struct seg_node
{
	multi_dot lft,rgt,mx;
	long long sum;
};
inline void pre_merge(multi_dot &a,multi_dot &b,multi_dot &ans,point dx)
{
	ans.cnt=-1;
	for(int i=0;i<=a.size();i++)ans.pb(a[i]);
	for(int i=1;i<=b.size();i++)ans.pb(b[i]+dx);
}
int st[maxn];
node the_ans[maxm];
struct query
{
	int l,r;
	int type;
	int dx;
}q[maxm];
struct my_vector
{
	unsigned long long a[maxm];
	int siz;
	__inline int size(){return siz;}
	__inline void push_back(unsigned long long t){a[siz++]=t;}
	__inline void clear(){siz=0;}
	__inline unsigned long long operator [](int t){return a[t];}
};
unsigned long long tmp[maxm];
unsigned int bu[1<<11];
void sort(unsigned long long *st,unsigned long long *ed,unsigned long long n,unsigned int bit)
{
	memset(bu,0,sizeof(bu));
	for(unsigned int i=0;i<n;i++)bu[(st[i]>>bit)&(0x7ff)]++;
	for(unsigned int i=1;i<(1<<11);i++)bu[i]+=bu[i-1];
	for(int i=n-1;i>=0;i--)ed[--bu[(st[i]>>bit)&0x7ff]]=st[i];
}
//sort 11 bit every time
void sort(unsigned long long *st,int n)
{
	sort(st,tmp,n,0);
	sort(tmp,st,n,11);
	sort(st,tmp,n,22);
	memcpy(tmp,st,sizeof(long long)*n);
}
//sort 33 bit.
int block_siz;
inline void sort(my_vector &qq)
{
	if(qq.siz>=1500)sort(qq.a,qq.siz);
	else sort(qq.a,qq.a+qq.siz,[](unsigned long long a,unsigned long long b){return (a&0x1ffffffff)<(b&0x1ffffffff);});//lambda!
}
int n,m;
struct seg
{
	big_memory_pool pool;
	seg_node nodes[maxn<<2];
	my_vector now_q;
	long long lazy[maxn<<2];
	__inline int ls(int x){return x<<1;}__inline int rs(int x){return (x<<1)|1;}
	inline void push_up(int now,int l,int r)
	{
		seg_node& lt=nodes[ls(now)],&rt=nodes[rs(now)];
		seg_node& ans=nodes[now];
        ans.lft.cnt=ans.rgt.cnt=ans.mx.cnt=r-l+1;
        ans.lft.clear(),ans.rgt.clear(),ans.mx.clear();
		int mid=(l+r)>>1;
		pre_merge(lt.lft,rt.lft,ans.lft,(point){mid-l+1,lt.sum});
		pre_merge(rt.rgt,lt.rgt,ans.rgt,(point){r-mid,rt.sum});
		for(int i=0;i<=lt.mx.size();i++)ans.mx.insert(lt.mx[i]);
		for(int i=0;i<=rt.mx.size();i++)ans.mx.insert(rt.mx[i]);
		merge(lt.rgt,rt.lft,ans.mx);
		ans.sum=lt.sum+rt.sum;
		ans.mx.get_convex_hull();ans.lft.get_convex_hull();ans.rgt.get_convex_hull();
	}
	inline void init(int now,int l,int r)
	{
		seg_node &ans=nodes[now];
		ans.lft=pool.get_area(r-l+2);ans.rgt=pool.get_area(r-l+2);ans.mx=pool.get_area(r-l+2);
		if(l==r)return;
		int mid=(l+r)>>1;
		init(ls(now),l,mid);
		init(rs(now),mid+1,r);
	}
	inline void build(int now,int l,int r,int *st)
	{
        lazy[now]=0;
		if(l==r)
		{
			seg_node &ans=nodes[now];
			ans.lft.cnt=1;ans.rgt.cnt=1;ans.mx.cnt=1;
			ans.lft.clear();ans.rgt.clear();ans.mx.clear();
			ans.lft.insert({0,0});ans.lft.insert({1,st[l]});
			ans.rgt.insert({0,0});ans.rgt.insert({1,st[l]});
			ans.mx.insert({0,0});ans.mx.insert({1,st[l]});
			ans.sum=st[l];
			return;
		}
		int mid=(l+r)>>1;
		build(ls(now),l,mid,st);
		build(rs(now),mid+1,r,st);
		push_up(now,l,r);
	}
	__inline void all_query(int t)
	{
		now_q.push_back((t*1ull<<33)+0x100000000ull+lazy[1]);//big enough
	}
	__inline void add_tag(int now,int l,int r,long long tag)
	{
		lazy[now]+=tag;
		nodes[now].lft.tag+=tag;nodes[now].rgt.tag+=tag;nodes[now].mx.tag+=tag;
		nodes[now].sum+=(r-l+1)*tag;
	}
	__inline void all_change(int ddx)
	{
		add_tag(1,1,block_siz,ddx);
	}
	__inline void push_down(int now,int l,int r)
	{
		if(!lazy[now])return;
		int mid=(l+r)>>1;
		add_tag(ls(now),l,mid,lazy[now]);
		add_tag(rs(now),mid+1,r,lazy[now]);
		lazy[now]=0;
	}
	__inline void query(int now,int l,int r,int ql,int qr,int id,long long now_dx)
	{
		if(ql<=l&&r<=qr)
		{
			node tmp=
				{nodes[now].lft.query_once(now_dx),nodes[now].rgt.query_once(now_dx),nodes[now].mx.query_once(now_dx),nodes[now].sum+now_dx*(r-l+1)};
			the_ans[id]=the_ans[id]+tmp;
//			cout<<now<<' '<<l<<' '<<r<<' '<<tmp.ls<<' '<<tmp.rs<<' '<<tmp.mx<<' '<<now_dx<<" "<<nodes[now].lft.tag<<'\n';
			return;
		}//push_down(now,l,r);
		int mid=(l+r)>>1;
		if(ql<=mid)query(ls(now),l,mid,ql,qr,id,now_dx+lazy[now]);
		if(mid<qr)query(rs(now),mid+1,r,ql,qr,id,now_dx+lazy[now]);
	}
	inline void change(int now,int l,int r,int ql,int qr,long long dx)
	{
		if(ql<=l&&r<=qr)
		{
			add_tag(now,l,r,dx);
			return;
		}
		push_down(now,l,r);
		int mid=(l+r)>>1;
		if(ql<=mid)change(ls(now),l,mid,ql,qr,dx);
		if(mid<qr)change(rs(now),mid+1,r,ql,qr,dx);
		push_up(now,l,r);
	}
	__inline void change(int ql,int qr,long long dx)
	{
		sort(now_q);
		seg_node res=nodes[1];res.sum-=res.lft.tag*block_siz,res.lft.tag=res.rgt.tag=res.mx.tag=0;
		for(int i=0;i<now_q.size();i++)
		{
			long long tmp=now_q[i]&0x1ffffffffull;
			tmp-=0x100000000ull;
			the_ans[now_q[i]>>33]=
				the_ans[now_q[i]>>33]+(node){res.lft.query(tmp),res.rgt.query(tmp),res.mx.query(tmp),res.sum+tmp*block_siz};
		}
		now_q.clear();
		change(1,1,block_siz,ql,qr,dx);
	}
}tree;
signed main()
{
	freopen("data.txt","r",stdin);freopen("data.out","w",stdout);
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>st[i];
	for(int i=1;i<=m;i++)
		(cin>>q[i].type>>q[i].l>>q[i].r),q[i].type==1?(cin>>q[i].dx),0:0;
	for(int l=1;l<=n;l+=siz)
	{
		int r=min(l+siz-1,n);
		block_siz=r-l+1;
		if(block_siz!=siz||l==1)
			tree.pool.del(tree.pool.pool),tree.init(1,1,block_siz);
		tree.build(1,1,block_siz,st+l-1);
		for(int x=1;x<=m;x++)
		{
			if(q[x].r<l||r<q[x].l)continue;
			else if(q[x].type==1)
				if(q[x].l<=l&&r<=q[x].r)
					tree.all_change(q[x].dx);
				else
					tree.change(max(q[x].l-l+1,1),min(q[x].r-l+1,block_siz),q[x].dx);
			else
				if(q[x].l<=l&&r<=q[x].r)
					tree.all_query(x);
				else
					tree.query(1,1,block_siz,max(q[x].l-l+1,1),min(q[x].r-l+1,block_siz),x,0);
		}
        tree.change(1,block_siz,0);
	}
	for(int i=1;i<=m;i++)
		if(q[i].type==2)cout<<the_ans[i].mx<<'\n';
	return 0;
}
2025/6/16 16:48
加载中...