8.15考试总结(NOIP模拟40)[送花·星空·零一串]

我只对现实世界绝望过,却未对自己绝望过!

T1 送花

解题思路

线段树维护序列。

我们暴力枚举右端点,用线段树搞出当前右端点的最优的左端点的值。

假设当前扫到的右端点是 r ,颜色是 col。

这种颜色的上一个位置为 las ,上上个位置为 pre。

那么就给 \([pre,las]\) 这个区间减去 \(val_{col}\)

\([las+1,r]\) 这个区间加上 \(val_{col}\)

更新之后统计答案就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e6+10;
int n,m,ans,las[N],s[N],val[N];
struct Segment_Tree
{
	int dat,laz;
}tre[N<<2];
vector<int> v[N];
void push_down(int x)
{
	if(!tre[x].laz)	return ;
	tre[ls].laz+=tre[x].laz;
	tre[rs].laz+=tre[x].laz;
	tre[ls].dat+=tre[x].laz;
	tre[rs].dat+=tre[x].laz;
	tre[x].laz=0;
}
void push_up(int x)
{
	tre[x].dat=max(tre[ls].dat,tre[rs].dat);
}
void update(int x,int l,int r,int L,int R,int num)
{
	if(L<=l&&r<=R)
	{
		tre[x].dat+=num;
		tre[x].laz+=num;
		return ;
	}
	push_down(x);
	int mid=(l+r)>>1;
	if(L<=mid)	update(ls,l,mid,L,R,num);
	if(R>mid)	update(rs,mid+1,r,L,R,num);
	push_up(x);
}
signed main()
{
	n=read();	m=read();
	for(int i=1;i<=n;i++)
	{
		s[i]=read();
		v[s[i]].push_back(i);
	}
	for(int i=1;i<=m;i++)
		for(int j=1;j<v[i].size();j++)
			las[v[i][j]]=v[i][j-1];
	for(int i=1;i<=m;i++)
		val[i]=read();
	for(int i=1;i<=n;i++)
	{
		int num=s[i];
		if(las[i])	update(1,1,n,max(1ll,las[las[i]]),las[i],-val[num]);
		update(1,1,n,las[i]+1,i,val[num]);
		ans=max(ans,tre[1].dat);
	}
	printf("%lld",ans);
	return 0;
}

T2 星空

解题思路

考场上就想到了一半的思路,然后后面就不会了。。

可惜我的\(n^2\)算法竟然只和隔壁 fengwu 卡时间的 \(n^3log^3n\) 的算法一样只得了 70pts。

把题面上的柿子拆开就变成了\(|x_1-x_2|=|y_1-y_2|\)

就剩下了两种情况:也就是斜率为 1 或者 -1 的一次函数上的点都可以缩成一个点。

然后发现我们可以通过旋转坐标轴来实现。

设之前的坐标为 \((x,y)\) 那么变换之后的坐标就是 \((x-y,x+y)\)

然后发现其实通过 x 坐标之间, y 坐标之间的加减之后取个 min 就是答案。

可以把更改坐标之后的值分别按 x 和 y 排序。

然后每个点和后面一个点之间的距离就是最小合法距离。

在更新的时候同时记录合法的并查集对。

去重之后把每条边两边的并查集大小乘积加起来就是答案了。

code

70pts

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=5e3+10,M=1e5+10,INF=0x3f3f3f3f3f3f3f3f;
struct Node
{
	int x,y;
}s[M];
int n,top,ans,minn=INF,sta[M],fa[M],val[N][N];
bool vis[N];
vector<int> v[M];
unordered_map<int,int> mp1,mp2;
priority_queue<pair<int,int> > q;
int find(int x)
{
	if(fa[x]==x)	return x;
	return fa[x]=find(fa[x]);
}
signed main()
{
	n=read();
	for(int i=1,x,y;i<=n;i++)
	{
		fa[i]=i;
		x=read();	y=read();
		s[i]=(Node){x,y};
	}
	for(int i=1;i<=n;i++)
	{
		auto it1=mp1.find(s[i].x-s[i].y);
		auto it2=mp2.find(s[i].x+s[i].y);
		if(it1==mp1.end()&&it2==mp2.end())
		{
			mp1.insert(make_pair(s[i].x-s[i].y,i));
			mp2.insert(make_pair(s[i].x+s[i].y,i));
			continue;
		}
		if(it1!=mp1.end()&&it2!=mp2.end())
		{
			fa[find(mp1[s[i].x-s[i].y])]=find(mp2[s[i].x+s[i].y]);
			fa[i]=find(mp1[s[i].x-s[i].y]);
			continue;
		}
		if(it1!=mp1.end())
		{
			fa[i]=find(mp1[s[i].x-s[i].y]);
			mp2.insert(make_pair(s[i].x+s[i].y,fa[i]));
			continue;
		}
		fa[i]=find(mp2[s[i].x+s[i].y]);
		mp1.insert(make_pair(s[i].x-s[i].y,fa[i]));
	}
	for(int i=1;i<=n;i++)
	{
		if(find(i)==i)	sta[++top]=i;
		v[find(i)].push_back(i);
	}
	memset(val,0x3f,sizeof(val));
	for(int i=1;i<=top;i++)
		for(int j=0;j<v[sta[i]].size();j++)
			for(int k=1;k<=n;k++)
				if(find(k)!=sta[i])
					val[sta[i]][find(k)]=min(val[sta[i]][find(k)],abs(abs(s[v[sta[i]][j]].x-s[k].x)-abs(s[v[sta[i]][j]].y-s[k].y)));
	for(int i=1;i<=top;i++)
	{
		for(int j=i+1;j<=top;j++)
			if(val[sta[i]][sta[j]]&&val[sta[i]][sta[j]]<minn)
			{
				minn=val[sta[i]][sta[j]];
				ans=v[sta[i]].size()*v[sta[j]].size();
			}
			else	if(val[sta[i]][sta[j]]==minn)
				ans+=v[sta[i]].size()*v[sta[j]].size();
	}
	if(minn>=INF)	printf("-1");
	else	printf("%lld\n%lld",minn,ans);
	return 0;
}

正解

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=5e3+10,M=1e5+10,INF=0x3f3f3f3f3f3f3f3f;
struct Node
{
	int x,y,id;
}s[M];
int n,ans,minn=INF,fa[M],siz[M];
vector<pair<int,int> > vec;
unordered_map<int,int> mp1,mp2;
int find(int x)
{
	if(fa[x]==x)	return x;
	return fa[x]=find(fa[x]);
}
bool comp1(Node a,Node b)
{
	return a.x<b.x;
}
bool comp2(Node a,Node b)
{
	return a.y<b.y;
}
signed main()
{
	n=read();
	for(int i=1,x,y;i<=n;i++)
	{
		fa[i]=i;
		x=read();	y=read();
		s[i]=(Node){x,y,i};
	}
	for(int i=1;i<=n;i++)
	{
		auto it1=mp1.find(s[i].x-s[i].y);
		auto it2=mp2.find(s[i].x+s[i].y);
		if(it1==mp1.end()&&it2==mp2.end())
		{
			mp1.insert(make_pair(s[i].x-s[i].y,i));
			mp2.insert(make_pair(s[i].x+s[i].y,i));
			continue;
		}
		if(it1!=mp1.end()&&it2!=mp2.end())
		{
			fa[find(mp1[s[i].x-s[i].y])]=find(mp2[s[i].x+s[i].y]);
			fa[i]=find(mp1[s[i].x-s[i].y]);
			continue;
		}
		if(it1!=mp1.end())
		{
			fa[i]=find(mp1[s[i].x-s[i].y]);
			mp2.insert(make_pair(s[i].x+s[i].y,fa[i]));
			continue;
		}
		fa[i]=find(mp2[s[i].x+s[i].y]);
		mp1.insert(make_pair(s[i].x-s[i].y,fa[i]));
	}
	for(int i=1;i<=n;i++)
	{
		siz[find(i)]++;
		s[i]=(Node){s[i].x-s[i].y,s[i].x+s[i].y,i};
	}
	sort(s+1,s+n+1,comp1);
	for(int i=1;i<=n;i++)
	{
		int j=i+1;
		int temp=min(abs(s[i].x-s[j].x),abs(s[i].y-s[j].y));
		if(temp)	minn=min(minn,temp);
	}
	sort(s+1,s+n+1,comp2);
	for(int i=1;i<=n;i++)
	{
		int j=i+1;
		int temp=min(abs(s[i].x-s[j].x),abs(s[i].y-s[j].y));
		if(temp)	minn=min(minn,temp);
	}
	sort(s+1,s+n+1,comp1);
	for(int i=1;i<=n;i++)
	{
		int j=i+1;
		int temp=min(abs(s[i].x-s[j].x),abs(s[i].y-s[j].y));
		int x=find(s[i].id),y=find(s[j].id);
		if(x>y)	swap(x,y);
		if(temp==minn)	vec.push_back(make_pair(x,y));
	}
	sort(s+1,s+n+1,comp2);
	for(int i=1;i<=n;i++)
	{
		int j=i+1;
		int temp=min(abs(s[i].x-s[j].x),abs(s[i].y-s[j].y));
		int x=find(s[i].id),y=find(s[j].id);
		if(x>y)	swap(x,y);
		if(temp==minn)	vec.push_back(make_pair(x,y));
	}
	sort(vec.begin(),vec.end());
	vec.erase(unique(vec.begin(),vec.end()),vec.end());
	for(int i=0;i<vec.size();i++)
		ans+=siz[vec[i].first]*siz[vec[i].second];
	if(minn>=INF)	printf("-1");
	else	printf("%lld\n%lld",minn,ans);
	return 0;
}

T3 零一串

大坑未补

posted @ 2021-08-18 16:16  Varuxn  阅读(107)  评论(0编辑  收藏  举报