[CLYZ2017]day2
冒泡排序
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.
字符串匹配
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;
}
阅读
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;
}