模拟92 考试总结

错失机会++

考试经过

T1发现是水题,和暴力拍了几下然后改改加几个特判就过了
T2不太会,看T3,发现60分比较好拿,看了一眼T4,这不是三元环?突然想写T4,于是开码,觉得空间有点悬于是卡了卡
map换成unordered_map就极限数据2s了,觉得没事,然后看T3
T3立刻写了一个\(n^3\)暴力,想着60,结果发现极限数据0.2,仔细想好像是\(n^2\ln\)的,于是不管了
T2想打暴力,发现不会,部分分T了,所以最后也没拿到分
100+0+100+100=300,出分一看3个AK的
马师傅\(10:30\)AK,然后开始快乐AKIOI。。。%就完事了

T1.石子合并

如果有正有负,那么一定可以构造出一种方案使得所有的贡献都是绝对值之和
全正全负就牺牲绝对值最小的变成负贡献,注意特判1
主要是数据范围会提示这样的直接扫的做法

#include <bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x*f;	
}
signed main()
{
	freopen("stone.in","r",stdin);
	freopen("stone.out","w",stdout);
	int t;cin>>t;
	while(t--)
	{
		int n=read(),mi=1e9,ans=0,cnt=0;
		if(n==1){printf("%d\n",read());continue;}
		for(int i=1;i<=n;i++)
		{
			int x=read();ans+=abs(x);mi=min(mi,abs(x));			
			if(x>=0)cnt++;
		}
		if(cnt==n||cnt==0)printf("%d\n",ans-2*mi);
		else printf("%d\n",ans);
	}
	return 0;	
}

T2.翻转游戏

当我一看见前缀后缀的时候仿佛明白了一切
\(n-1\)个矩形的交,预处理前后缀的交,然后枚举哪个不选,最后减去\(n\)个的交

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=300050;
struct node{
	int x,l,y,r;
	inline bool ck()
	{
		if(x==0&&l==0&&r==0&&y==0)return 0;
		else return 1;	
	}
	inline int gett()
	{
		if(!ck())return 0;
		return (y-x+1)*(r-l+1);
	}
	inline void print()
	{
		cout<<"x"<<x<<"l"<<l<<"y"<<y<<"r"<<r<<endl;
	}
}a[N],b[N],c[N];
int p,q,n;
inline bool check(node p1,node p2)
{
	if(p1.l>p2.l)swap(p1,p2);
	if(p1.r<p2.l||p1.y<p2.x||p2.y<p1.x)return 0;
	return 1;
}
inline node get(node p1,node p2)
{
	if(!check(p1,p2))return (node){0,0,0,0};
	return (node){max(p1.x,p2.x),max(p1.l,p2.l),min(p2.y,p1.y),min(p1.r,p2.r)};
}
inline node gan()
{	
	node pp=(node){1,1,(int)1e9,(int)1e9};
	for(int i=1;i<=n;i++)
	{
		if(!check(a[i],pp))return (node){0,0,0,0};
		pp=get(pp,a[i]);
	}
	return (pp.r==1e9)?(node){0,0,0,0}:pp;
}
signed main()
{	
	freopen("carpet.in", "r", stdin);
   freopen("carpet.out", "w", stdout);
	int T;cin>>T;
	while(T--)
	{
		memset(b,0,sizeof(b));memset(c,0,sizeof(c));
		scanf("%lld%lld%lld",&p,&q,&n);
		for(int i=1;i<=n;i++)scanf("%lld%lld%lld%lld",&a[i].x,&a[i].l,&a[i].y,&a[i].r),a[i].x++,a[i].l++;
		b[0]=c[n+1]=(node){0,0,(int)1e9,(int)1e9};int ans=0;
		for(int i=1;i<=n;i++)b[i]=get(b[i-1],a[i]);
		for(int i=n;i>=1;i--)c[i]=get(c[i+1],a[i]);
		for(int i=1;i<=n;i++)ans+=get(b[i-1],c[i+1]).gett();
		ans-=gan().gett()*(n-1);cout<<ans<<endl;
	}
	return 0;
}

感觉自己像个zz

T3.优美的旋律

枚举字符串,然后枚举他的倍数,哈希判断是否合法,复杂度\(n^2\ln n\)
可以通过打标记来优化到\(n^2\),但由于常数小已经可过

T4.基站建设

无向图三元环板子,找出来环之后判断
拿哈希表暴力存储,发现空间刚好够,然后最后枚举出答案即可
复杂度\(m\sqrt m\)自带超大常数

#include <bits/stdc++.h>
using namespace std;
#define int unsigned int 
#define pir pair<int,int> 
const int N=50050,M=200050;
inline int read()
{
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;	
}
struct node{
	int from,to,next;
}a[2*M];
int head[N],mm=1;
inline void add(int x,int y)
{
	a[mm].from=x;a[mm].to=y;
	a[mm].next=head[x];head[x]=mm++;
}
unordered_map <int,int> mp;
int c[450*N][2],n,m,w[N],tot,id[450*N];
inline int ganhash(int x,int y)
{	
	return x*50001+y;
}
inline void ganid(int x,int y,int z)
{
	int idd;
	if(mp.find(ganhash(x,y))!=mp.end())idd=mp[ganhash(x,y)];
	else if(mp.find(ganhash(y,x))!=mp.end())idd=mp[ganhash(y,x)];
	else idd=++tot,mp.insert(make_pair(ganhash(x,y),idd)),id[idd]=ganhash(x,y);
	if(!c[idd][0])c[idd][0]=z;
	else if(!c[idd][1])
	{
		c[idd][1]=z;if(w[c[idd][0]]<w[c[idd][1]])swap(c[idd][0],c[idd][1]);
	}
	else
	{
		if(w[z]<=w[c[idd][1]])return;
		else if(w[z]<=w[c[idd][0]])c[idd][1]=z;
		else c[idd][1]=c[idd][0],c[idd][0]=z;		
	}
}
inline void gan(int x,int y,int z)
{
	ganid(x,y,z);ganid(x,z,y);
	ganid(y,z,x);
}
int fr[M],to[M],du[N],v[N];
signed main()
{
	freopen("station.in","r",stdin);
	freopen("station.out","w",stdout);
	cin>>n>>m;int sum=0;
	for(int i=1;i<=n;i++)w[i]=read();
	for(int i=1;i<=m;i++)
	{
		fr[i]=read(),to[i]=read();
		du[fr[i]]++;du[to[i]]++;
	}
	for(int i=1;i<=m;i++)
	{
		int x=fr[i],y=to[i];
		if(du[x]<du[y]||(du[x]==du[y]&&x<y))swap(x,y);
		add(x,y);
	}
	for(int x=1;x<=n;x++)
	{
		for(int i=head[x];i;i=a[i].next)v[a[i].to]=x;
		for(int i=head[x];i;i=a[i].next)
		{
			int y=a[i].to;
			for(int j=head[y];j;j=a[j].next)
			{
				int z=a[j].to;
				if(v[z]==x)gan(x,y,z);
			}
		}
	}
	int ans=0;
	for(int i=1;i<=tot;i++)
	{
		if(!(w[c[i][0]]*w[c[i][1]]))continue;
		int x=id[i]/50001,y=id[i]%50001;
		ans=max(ans,w[c[i][0]]*w[c[i][1]]+(w[x]+1)*(w[y]+1));
	}
	cout<<ans<<endl;
	return 0;
}

考试总结

思维一定要到,能做的题不要考玩才后悔
不要乱看题,很耽误时间,容易慌,要把题想进去,别犹豫

posted @ 2021-11-08 07:26  D'A'T  阅读(35)  评论(0编辑  收藏  举报