寻找宝藏

  • 树状数组可以用来维护前缀最大值
  • 把矩形按某个坐标排序来处理问题的思想
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int p[300005],v[300005],n,m;
long long ans[300005],tmp[300005],f[300005],g[300005],h[300005],c[300005];
struct t1
{
	int x1,y1,x2,y2,id;
}t[300005];
int read1()
{
	char cc=getchar();
	while(!(cc>=48&&cc<=57))
	{
		if(cc=='-')
		{
			break;
		}
		cc=getchar();
	}
	bool f=false;
	int s=0;
	if(cc=='-')
	{
		f=true;
	}
	else
	{
		s=cc-48;
	}
	while(1)
	{
		cc=getchar();
		if(cc>=48&&cc<=57)
		{
			s=s*10+cc-48;
		}
		else
		{
			break;
		}
	}
	if(f==true)
	{
		s=-s;
	}
	return s;
}
int lowbit(int n)
{
	return n&(-n);
}
void add(int n1,long long va)
{
	while(n1<=n)
	{
		c[n1]=max(c[n1],va);
		n1+=lowbit(n1);
	}
}
long long ask(int n1)
{
	long long s=0;
	while(n1>0)
	{
		s=max(s,c[n1]);
		n1-=lowbit(n1);
	}
	return s;
}
bool cmpx1(t1 a,t1 b)
{
	return a.x1<b.x1;
}
bool cmpx2(t1 a,t1 b)
{
	return a.x2>b.x2;
}
void solve1()
{
	for(int i=1;i<=n;i++)
	{
		c[i]=0;
	}
	sort(t+1,t+m+1,cmpx1);
	int j=0;
	for(int i=1;i<=m;i++)
	{
		while(j+1<=n&&j+1<t[i].x1)
		{
			j++;
			add(n+1-p[j],h[j]);
		}
		ans[t[i].id]=max(ans[t[i].id],ask(n+1-(t[i].y2+1)));
	}
}
void solve2()
{
	for(int i=1;i<=n;i++)
	{
		c[i]=0;
	}
	sort(t+1,t+m+1,cmpx2);
	int j=n+1;
	for(int i=1;i<=m;i++)
	{
		while(j-1>=1&&j-1>t[i].x2)
		{
			j--;
			add(p[j],h[j]);
		}
		ans[t[i].id]=max(ans[t[i].id],ask(t[i].y1-1));
	}
}
void solve3()
{
	for(int i=1;i<=n;i++)
	{
		c[i]=0;
	}
	sort(t+1,t+m+1,cmpx1);
	int j=0;
	for(int i=1;i<=m;i++)
	{
		while(j+1<=n&&j+1<t[i].x1)
		{
			j++;
			add(p[j],f[j]);
		}
		tmp[t[i].id]=ask(t[i].y2);
	}
	for(int i=1;i<=n;i++)
	{
		c[i]=0;
	}
	j=n+1;
	for(int i=m;i>=1;i--)
	{
		while(j-1>=1&&j-1>=t[i].x1)
		{
			j--;
			add(n+1-p[j],g[j]);
		}
		tmp[t[i].id]+=ask(n+1-(t[i].y2+1));
		ans[t[i].id]=max(ans[t[i].id],tmp[t[i].id]);
	}
}
void solve4()
{
	for(int i=1;i<=n;i++)
	{
		c[i]=0;
	}
	sort(t+1,t+m+1,cmpx2);
	int j=0;
	for(int i=m;i>=1;i--)
	{
		while(j+1<=n&&j+1<=t[i].x2)
		{
			j++;
			add(p[j],f[j]);
		}
		tmp[t[i].id]=ask(t[i].y1-1);
	}
	for(int i=1;i<=n;i++)
	{
		c[i]=0;
	}
	j=n+1;
	for(int i=1;i<=m;i++)
	{
		while(j-1>=1&&j-1>t[i].x2)
		{
			j--;
			add(n+1-p[j],g[j]);
		}
		tmp[t[i].id]+=ask(n+1-t[i].y1);
		ans[t[i].id]=max(ans[t[i].id],tmp[t[i].id]);
	}
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		for(int i=1;i<=n;i++)
		{
			c[i]=0;
		}
		for(int i=1;i<=n;i++)
		{
			p[i]=read1();
			v[i]=read1();
			f[i]=v[i]+ask(p[i]);
			add(p[i],f[i]);
		}
		for(int i=1;i<=n;i++)
		{
			c[i]=0;
		}
		for(int i=n;i>=1;i--)
		{
			g[i]=v[i]+ask(n+1-p[i]);
			add(n+1-p[i],g[i]);
			h[i]=f[i]+g[i]-v[i];
		}
		for(int i=1;i<=m;i++)
		{
			t[i].x1=read1();
			t[i].y1=read1();
			t[i].x2=read1();
			t[i].y2=read1();
			t[i].id=i;
		}
		solve1();
		solve2();
		solve3();
		solve4();
		for(int i=1;i<=m;i++)
		{
			printf("%lld\n",ans[i]);
			ans[i]=0;
		}
	}
	return 0;
}
posted @ 2024-07-30 15:52  D06  阅读(4)  评论(0编辑  收藏  举报