2022.7.13 模拟赛

2022.7.13 模拟赛#

link

最大序列#

思路

首先出栈的必然是最大的数

设每次出栈的数在 i

然后不断比较 i1 处的数和 in 中最大的数,判断往哪边出栈

细节很多 貌似就只有我一个人写了76行的代码,其余人都是30多行

#include<bits/stdc++.h>
using namespace std;

const int N=2e5+5;

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

int n,now;
int a[N],b[N];
int f[N],l[N],g[N];
bool vis[N];

inline int find(int x){
	return l[x]==x?x:l[x]=find(l[x]);
}

inline int get(int x){
	return g[f[x]]==1?f[x]=get(f[x]):f[x];
}

signed main(){
	n=read();
	for(int i=1;i<=n;++i){
		a[i]=read();
		b[a[i]]=i;
		if(a[i]==n) now=i,vis[i]=1;
	}
	int mx=n;
	f[n]=g[n]=n;
	for(int i=n-1;i;--i){
		f[i]=g[i]=mx;
		if(a[i]>a[mx])
			mx=i;
	}
	int cnt=0;
	printf("%d ",n);
	a[n+1]=a[n+2]=1e9;
	for(int i=1;i<=n;++i) l[i]=i;
	l[b[n]]=b[n]-1;
	g[b[n]]=1;
	while(cnt<n-1){
		if(now==n) break;
		if(find(now)==0){
			now=get(now);
			printf("%d ",a[now]);
			vis[now]=1;
			l[now]=find(now-1);
			g[now]=1;
			++cnt;
			continue;
		}
		int x=a[get(now)],y=a[find(now)];
		//cout<<x<<" "<<y<<endl;
		if(y<x){
			vis[b[x]]=1;
			printf("%d ",x);
			now=b[x];
			l[b[x]]=find(b[x]-1);
			g[now]=1;
		}
		else{
			vis[b[y]]=1;
			printf("%d ",y);
			now=b[y];
			l[now]=find(now-1);
			g[now]=1;
		}
		++cnt;
	}
	for(int i=n;i;--i) if(!vis[i]) printf("%d ",a[i]);
}

调了 1h qaq

思考熊的马拉松#

这个题实际上是把速度 a1n 从小到大排序,然后求:

i=1nj=1i1(aiaj)Lamax

首先考虑 amax|L 的部分分

这部分 Lamax 实际上可以当作一个常数 k,可以考虑将其提出来然后求的式子就变成了:

ki=1nj=1,aj<ain(aiaj)

考虑每个数的贡献,容易得到第 i 个数的贡献是由两部分 i1(ni) 组成,所以贡献为 i1(ni)=2i1n

这个做法给了我们满分的启示:统计每一个数的贡献

但由于原式要向下取整,所以分类讨论

假设 bi=(aiL)modamax,那么:

  • bibj 时,(aiaj)Lamax=aiLamaxajLamax

  • bi<bj 时,(aiaj)Lamax=aiLamaxajLamax1

化简之后的式子中的两个部分都可以按照贡献统计,然后还要减去 i>jbi<bj 的部分

这不就是逆序对吗?采用归并排序求逆序对

此题做完了,时间复杂度 O(Tnlogn)

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N=2e5+5;

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

int n,A,L,mx,num;
int a[N],s[N],b[N],tmp[N];

inline void doge(){
	int ans=0;
	for(int i=n;i;--i){
		ans+=1ll*(i-1)*a[i]-s[i-1];
	}
	cout<<ans*(L/mx)<<endl;
}

inline void merge(int l,int r){
	if(l==r) return;
	int mid=l+r>>1;
	merge(l,mid),merge(mid+1,r);
	int i=l,j=mid+1,cnt=l-1;
	while(i<=mid&&j<=r){
		if(b[i]>b[j]) num+=mid-i+1,tmp[++cnt]=b[j++];
		else tmp[++cnt]=b[i++];
	}
	while(i<=mid) tmp[++cnt]=b[i++];
	while(j<=r) tmp[++cnt]=b[j++];
	for(int i=l;i<=r;++i) b[i]=tmp[i];
}

inline void cat(){
	num=0;
	for(int i=1;i<=n;++i) b[i]=a[i]%mx*L%mx;
	merge(1,n);
	int res=0;
	for(int i=1;i<=n;++i){
		res+=(i*2-n-1)*((a[i]*L)/mx);
	}
	cout<<res-num<<endl;
}

inline void solve(){
	n=read(),A=read(),L=read();
	for(int i=1;i<=n;++i) a[i]=read();
	sort(a+1,a+n+1);
	mx=a[n];
	for(int i=1;i<=n;++i) s[i]=s[i-1]+a[i];
	if(L%mx==0) doge();
	else cat();
}

signed main(){
	int T=read();read();
	while(T--)
		solve();
}

疏散演习#

这题是个玄学骗分题

我打了 30pts 的暴力然后走人

下标#

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+5;

#define next ijlkjdashadshfhauisehgfiawbesfdyhgwasdafiuhedsuafhuisagdiufgadsiufguidasgfiagw

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

int n,top;
char s[N];
int cnt[N],st[N],next[N],match[N];

inline bool check(int l0,int r0,int l1,int r1){
	for(int i=l0,j=l1;;i=next[i],j=next[j]){
		if(s[i]!=s[j]) return s[i]<s[j];
		if(i==r0||j==r1) return i==r0;
	}
}

inline void solve(int &l,int r){
	if(isalpha(s[r])) return;
	int mid=match[r];
	int x=mid-1,y=mid+1,end=r--;
	solve(l,x);solve(y,r);
	if(!check(l,x,y,r)) swap(l,y),swap(x,r);
	next[x]=mid;
	next[mid]=y;
	next[r]=end;
}

inline void work(){
	scanf("%s",s);
	n=strlen(s);
	for(int i=0;i<n;++i) next[i]=i+1;
	cnt[0]=0;
	for(int i=0;i<n;++i) cnt[i+1]=cnt[i]+(!isalpha(s[i]));
	top=0;
	memset(match,-1,sizeof(match));
	for(int i=0;i<n;++i)
		if(s[i]=='[') st[top++]=i;
		else if(s[i]==']') match[i]=st[--top];
	int x=0;
	solve(x,n-1);
	for(int i=x;i<n;i=next[i]) cout<<s[i];
	cout<<endl;
}

signed main(){
	int T=read();
	while(T--) work();
}

作者:Into_qwq

出处:https://www.cnblogs.com/into-qwq/p/16475186.html

版权:本作品采用「qwq」许可协议进行许可。

posted @   Into_qwq  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示