[CLYZ2017]day2

冒泡排序

image

Solution

30分

直接模拟.

70分

求出\(a\)中每个数之前比它大的数的个数,取\(max\).

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 1000005
using namespace std;
typedef long long ll;
int a[N],pre[N],n,s,b,c,d,cnt,ans;
inline int read(){
	int ret=0;char c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		ret=(ret<<1)+(ret<<3)+c-'0';
		c=getchar();
	}
	return ret;
}
inline bool chk(){
	for(int i=1;i<=n;++i)
		if(a[i]!=i)
			return false;
	return true; 
}
inline int lowbit(int x){
	return x&(-x);
}
inline int ask(int k){
	int ret=0;
	for(int i=k;i;i-=lowbit(i))
		ret+=pre[i];
	return ret;
}
inline void add(int k){
	for(int i=k;i<=n;i+=lowbit(i))
		++pre[i];
}
inline void Aireen(){
	scanf("%d%d%d%d%d",&n,&s,&b,&c,&d);
	for(int i=1,j,t;i<=n;++i){
		a[i]=i;
		s=(1ll*s*b+c)%d;
 		swap(a[i],a[s%i+1]);
	}
	if(n<=1000){
		int t;cnt=0;
		while(!chk()){
			++cnt;
			for(int i=1;i<n;++i)
				if(a[i]>a[i+1]){
					t=a[i];a[i]=a[i+1];a[i+1]=t;
				}
		}
		printf("%d\n",cnt);
		return;
	}
	for(int i=1;i<=n;++i){
		ans=max(ans,ask(n)-ask(a[i]));
		add(a[i]);
	}
	printf("%d\n",ans);
}
int main(){
	freopen("bubble.in","r",stdin);
	freopen("bubble.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

100分

\(ans=max\{i-a_i\}\).

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 30000005
using namespace std;
typedef long long ll;
int a[N],n,s,b,c,d,ans;
inline void Aireen(){
	scanf("%d%d%d%d%d",&n,&s,&b,&c,&d);
	for(register int i=1,j,t;i<=n;++i){
		a[i]=i;
		s=(1ll*s*b+c)%d;
 		swap(a[i],a[s%i+1]);
	}
	for(register int i=1;i<=n;++i)
		ans=max(ans,i-a[i]);
	printf("%d\n",ans);
}
int main(){
	freopen("bubble.in","r",stdin);
	freopen("bubble.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

代码问题

有些下标计算爆int.

字符串匹配

image

Solution

10分

暴力求解.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 1000005
using namespace std;
typedef long long ll;
int s[N],t[N],g[N],nxt[N],tot[N],ans[N],n,m,k,c,q,cnt,sum;
bool b[N];
inline int read(){
	int ret=0;char c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		ret=(ret<<1)+(ret<<3)+c-'0';
		c=getchar();
	}
	return ret;
}
inline bool chk(int u){
	for(int i=1;i<=c;++i) 
		for(int j=g[i],k=s[u+g[i]];j;j=nxt[j]){
			if(s[u+j]!=k) return false;
		} 
	return true;
}
inline void Aireen(){
	q=read();c=read();
	while(q--){
		n=read();m=read();
		for(int i=1;i<=n;++i)
			s[i]=read();
		for(int i=1;i<=m;++i)
			t[i]=read();
		memset(g,0,sizeof(g));
		memset(b,0,sizeof(b));
		memset(tot,0,sizeof(tot));
		if(n<m){
			puts("0");continue;
		}
		for(int i=m;i;--i){
			nxt[i]=g[t[i]];
			g[t[i]]=i;b[t[i]]=true;
		}
		k=cnt=sum=0;
		for(int i=1;i<=c;++i)
			if(b[i]) ++k;
		for(int i=1;i<m;++i){
			if(!tot[s[i]]) ++cnt;
			++tot[s[i]];
		}
		for(int i=0;i+m<=n;++i){
			if(!tot[s[i+m]]) ++cnt;
			++tot[s[i+m]];
			if(cnt==k&&chk(i))
				ans[++sum]=i+1;
			if(!(--tot[s[i+1]])) --cnt;
		}
		printf("%d\n",sum);
		for(int i=1;i<=sum;++i)
			printf("%d ",ans[i]);
		printf("\n"); 
	}
}
int main(){
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

100分

对字符串相同字符间的相邻距离进行\(kmp\).
会出现上一个相同字符不出现在目前匹配的子串中,在跳nxt的判断中,分类讨论即可.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 1000005
using namespace std;
int s[N],t[N],nxt[N],lst[N],ans[N],n,m,c,q,cnt;
inline int read(){
	int ret=0;char c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		ret=(ret<<1)+(ret<<3)+c-'0';
		c=getchar();
	}
	return ret;
}
inline bool chk1(int i,int j){
	if(j<t[i]) return !t[j+1];
	return t[j+1]==t[i];
}
inline bool chk2(int i,int j){
	if(j<s[i]) return !t[j+1];
	return t[j+1]==s[i];
}
inline void Aireen(){
	q=read();c=read();
	while(q--){
		n=read();m=read();
		for(int i=1;i<=n;++i)
			s[i]=read();
		for(int i=1;i<=m;++i)
			t[i]=read();
		if(n<m){
			puts("0");continue;
		}
		memset(lst,0,sizeof(lst));
		for(int i=1,k;i<=n;++i){
			if(!lst[s[i]]) k=0;
			else k=i-lst[s[i]];
			lst[s[i]]=i;s[i]=k;
		}
		s[n+1]=t[m+1]=-1;
		memset(lst,0,sizeof(lst));
		for(int i=1,k;i<=m;++i){
			if(!lst[t[i]]) k=0;
			else k=i-lst[t[i]];
			lst[t[i]]=i;t[i]=k;
		}
		cnt=0;
		memset(nxt,0,sizeof(nxt));
		for(int i=2,j=0;i<=m;++i){
			while(j&&!chk1(i,j)) j=nxt[j];
			if(chk1(i,j)) ++j;
			nxt[i]=j;
		}
		for(int i=1,j=0;i<=n;++i){
			while(j&&!chk2(i,j)) j=nxt[j];
			if(chk2(i,j)) ++j;
			if(j==m){
				ans[++cnt]=i-m+1;
				j=nxt[j];
			}
		}
		printf("%d\n",cnt);
		for(int i=1;i<=cnt;++i)
			printf("%d ",ans[i]);
		printf("\n");
	}
}
int main(){
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

阅读

image

Solution

20分

\(f[i]=max\{f[j]-\lceil\frac{t[i]-t[j]}{D}\rceil\times{A}\}+b[i]\).

50分

对于\(D\leq100\),对于每个\(t_i\;mod\;D\)同余的贪心.枚举\(mod\;D\)不同的值即可.

100分

可以发现,
\(t[j]<t[i]\)时,\(\lceil\frac{t[i]-t[j]}{D}\rceil=\lfloor\frac{t[i]}{D}\rfloor-\lfloor\frac{t[j]}{D}\rfloor+1\);
\(t[j]\geq{t[i]}\)时,\(\lceil\frac{t[i]-t[j]}{D}\rceil=\lfloor\frac{t[i]}{D}\rfloor-\lfloor\frac{t[j]}{D}\rfloor\);
\(f[i]-\lfloor\frac{m}{D}\rfloor-\lfloor\frac{k}{D}\rfloor=max\{max\{f[1...j-1]\}-a,max\{f[j...m]\}\}\)
(\(j\)表示\(mod\;D\)的值离散后的位置,离散后共有m个值).
最后全部加上\(\lfloor\frac{m}{D}\rfloor-\lfloor\frac{k}{D}\rfloor\)就好啦.
P.S.写代码的时候比较傻,所以写得正确性和简洁性堪忧.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100005
#define M 300005
using namespace std;
typedef long long ll;
ll f[N],g[N],b[N],t[N],a,d,m,k,ans;
int p[N],idp[N],ids[N],n,cnt;
inline int read(){
	int ret=0;char c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		ret=(ret<<1)+(ret<<3)+c-'0';
		c=getchar();
	}
	return ret;
}
//i比j优 
inline bool cmp(int i,int j){
	return f[i]+t[i]/d*a>f[j]+t[j]/d*a;
}
inline int lowbit(int k){
	return k&(-k);
}
inline void change(int k){
	for(int i=k;i<=cnt;i+=lowbit(i))
		if(!idp[i]||cmp(g[k],idp[i])) idp[i]=g[k]; 
	for(int i=cnt-k+1;i<=cnt;i+=lowbit(i)){
		if(!ids[i]||cmp(g[k],ids[i])) ids[i]=g[k];
	}
}
inline int pre(int k){
	int ret=0;
	for(int i=k;i;i-=lowbit(i))
		if(!ret) ret=idp[i];
		else if(cmp(idp[i],ret))
			ret=idp[i];
	return ret;
}
inline int suf(int k){
	int ret=0;
	for(int i=cnt-k+1;i;i-=lowbit(i))
		if(!ret) ret=ids[i];
		else if(cmp(ids[i],ret))
			ret=ids[i];
	return ret;
}
inline void Aireen(){
	scanf("%lld%lld%lld%lld%d",&k,&m,&d,&a,&n);
	for(int i=1;i<=n;++i)
		scanf("%lld%lld",&t[i],&b[i]);
	if(n<=1000){
		for(int i=1;i<=n;++i){
			if((t[i]-k)%d) f[i]=-((t[i]-k)/d+1ll)*a+b[i];
			else f[i]=-(t[i]-k)/d*a+b[i];
			for(int j=1;j<i;++j)
				if((t[i]-t[j])%d)
					f[i]=max(f[i],f[j]-((t[i]-t[j])/d+1ll)*a+b[i]);
				else f[i]=max(f[i],f[j]-(t[i]-t[j])/d*a+b[i]);
		}
		if((m-k)%d) ans=-((m-k)/d+1ll)*a;
		else ans=-(m-k)/d*a;
		for(int i=1;i<=n;++i)
			if((m-t[i])%d)
				ans=max(ans,f[i]-((m-t[i])/d+1ll)*a);
			else ans=max(ans,f[i]-(m-t[i])/d*a);
		printf("%lld\n",ans);
		return;
	}
	if(d<=100){
		for(int i=1;i<=n;++i){
			if((t[i]-k)%d) f[i]=-((t[i]-k)/d+1ll)*a+b[i];
			else f[i]=-(t[i]-k)/d*a+b[i];
			for(int k=(int)(d-1ll),j;k>=0;--k)
				if((t[i]-t[j=g[k]])%d)
					f[i]=max(f[i],f[j]-((t[i]-t[j])/d+1ll)*a+b[i]);
				else f[i]=max(f[i],f[j]-(t[i]-t[j])/d*a+b[i]);
			if(!g[t[i]%d]) g[t[i]%d]=i;
			else if(cmp(i,g[t[i]%d]))
				g[t[i]%d]=i;
		}
		if((m-k)%d) ans=-((m-k)/d+1ll)*a;
		else ans=-(m-k)/d*a;
		for(int i=1;i<=n;++i)
			if((m-t[i])%d)
				ans=max(ans,f[i]-((m-t[i])/d+1ll)*a);
			else ans=max(ans,f[i]-(m-t[i])/d*a);
		printf("%lld\n",ans);
		return;	
	}
	for(int i=1;i<=n;++i)
		p[i]=(int)(t[i]%d);
	sort(p+1,p+1+n);cnt=1;
	for(int i=2;i<=n;++i)
		if(p[i]!=p[i-1]) p[++cnt]=p[i];
	for(int i=1,j,l;i<=n;++i){
		if((t[i]-k)%d) f[i]=-((t[i]-k)/d+1ll)*a+b[i];
		else f[i]=-(t[i]-k)/d*a+b[i];
		l=lower_bound(p+1,p+1+cnt,(int)(t[i]%d))-p;
		if(l-1){
			j=pre(l-1);
			if(j){
				if((t[i]-t[j])%d) 
					f[i]=max(f[i],f[j]-((t[i]-t[j])/d+1ll)*a+b[i]);
				else f[i]=max(f[i],f[j]-(t[i]-t[j])/d*a+b[i]);
			}
		}
		j=suf(l);
		if(j){
			if((t[i]-t[j])%d) 
				f[i]=max(f[i],f[j]-((t[i]-t[j])/d+1ll)*a+b[i]);
			else f[i]=max(f[i],f[j]-(t[i]-t[j])/d*a+b[i]);
		}
		if(!g[l]){
			g[l]=i;change(l);
		}
		else if(cmp(i,g[l])){
			g[l]=i;change(l);
		}
	}
	if((m-k)%d) ans=-((m-k)/d+1ll)*a;
	else ans=-(m-k)/d*a;
	for(int i=1;i<=n;++i)
		if((m-t[i])%d)
			ans=max(ans,f[i]-((m-t[i])/d+1ll)*a);
		else ans=max(ans,f[i]-(m-t[i])/d*a);
	printf("%lld\n",ans);
}
int main(){
	freopen("reading.in","r",stdin);
	freopen("reading.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2021-11-26 20:14  Aireen_Ye  阅读(21)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.