Atcoder 437 总结+E-F题解

总结

A,B,C,D,E

考试时很快打出了正解,没什么问题。

F

没什么思路,下来发现了一种比较神奇的做法。

题解

E

会发现,每一层我们会将相同的数字以及他的儿子同时去遍历。因为它们有着相同的前缀,所以说字典序只在目前这个位置出现差异。

每一次我们用一个vector记录我们当前正在遍历哪些父亲,然后去看它的儿子又有哪些是相同的,然后再加相同的放进去去往下递归即可。

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=3e5+5;
int ans[maxn],cnt;
vector<int> s;
set<pair<int,int> > g[maxn];
void dfs()
{
	vector<pair<int,int> > v;
	for(auto x:s)
	{
		for(auto [w,to]:g[x]) v.push_back({w,to});
	}
	s.clear();
	sort(v.begin(),v.end());
	for(int i=0;i<v.size();i++)
	{
		ans[cnt++]=v[i].second;
		s.push_back(v[i].second);
		while(i<v.size()-1&&v[i+1].first==v[i].first) i++,s.push_back(v[i].second),ans[cnt++]=v[i].second;
		dfs();
		s.clear();
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x,y;cin>>x>>y;
		g[x].insert({y,i});
	}
	s.push_back(0);
	ans[++cnt]=0;
	dfs();
	for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
	return 0;
}

F

我们先把曼哈顿距离的式子写出来。

\[|X-x_i|+|Y-y_i| \]

那么此时我们就会发现我们将绝对值展开后得。

\[X+Y-(x_i+y_i)\\ x_i+y_i-(X+Y)\\ X-Y-(x_i-y_i)\\ x_i-y_i-(X-Y) \]

我们只需要将两个加起来的最大值最小值两个减掉的最小值最大值都用线段树维护出来即可。

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
int x[maxn],y[maxn];
struct SGT
{
	int maxx[maxn<<2],minn[maxn<<2];
	void pushup(int x)
	{
		maxx[x]=max(maxx[x*2],maxx[x*2+1]);
		minn[x]=min(minn[x*2],minn[x*2+1]);
	}
	void update(int x,int l,int r,int p,int v)
	{
		if(l==r)
		{
			maxx[x]=minn[x]=v;
			return;
		}
		int mid=(l+r)>>1;
		if(p<=mid) update(x*2,l,mid,p,v);
		else update(x*2+1,mid+1,r,p,v);
		pushup(x);
	}
	int querymax(int x,int l,int r,int lt,int rt)
	{
		if(l>=lt&&r<=rt) return maxx[x];
		int mid=(l+r)>>1,a=0,b=0;
		if(lt<=mid) a=querymax(x*2,l,mid,lt,rt);
		if(rt>mid) b=querymax(x*2+1,mid+1,r,lt,rt);
		return max({a,b});
	}
	int querymin(int x,int l,int r,int lt,int rt)
	{
		if(l>=lt&&r<=rt) return minn[x];
		int mid=(l+r)>>1,a=inf,b=inf;
		if(lt<=mid) a=querymin(x*2,l,mid,lt,rt);
		if(rt>mid) b=querymin(x*2+1,mid+1,r,lt,rt);
		return min({a,b});
	}
}trees,treed;
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n,q;cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		cin>>x[i]>>y[i];
		trees.update(1,1,n,i,x[i]+y[i]);
		treed.update(1,1,n,i,x[i]-y[i]);
	}
	while(q--)
	{
		int op;cin>>op;
		if(op==1)
		{
			int i,x,y;cin>>i>>x>>y;
			trees.update(1,1,n,i,x+y);
			treed.update(1,1,n,i,x-y);
		}
		else
		{
			int l,r,x,y;cin>>l>>r>>x>>y;
			int a=trees.querymax(1,1,n,l,r)-(x+y);
			int b=(x+y)-trees.querymin(1,1,n,l,r);
			int c=treed.querymax(1,1,n,l,r)-(x-y);
			int d=(x-y)-treed.querymin(1,1,n,l,r);
			cout<<max({a,b,c,d})<<endl;
		}
	}
	return 0;
}
posted @ 2025-12-21 15:29  Engle_Chen  阅读(28)  评论(0)    收藏  举报