[日志]12-10

我不是柳橙汁

2017-12-10 21:53:02

Personal

## 1.今天呢,我考了一套题目。 分数100/300。 很无奈。 ### sequence[模拟] 题面就是给你个序列,然后让你找出max{a[i]-a[j]}(i<j) 只要线性找最大值然后拿当前值减即可。 心态爆炸。只有50/100分。mod爆了。 ```cpp #include<cstdio> long long sa,sb,sc,sd,n,mode; long long a[5000010]; inline long long v_in(){ char ch=getchar(); long long sum=0,f=1; while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ sum=(sum<<3)+(sum<<1)+(ch^48); ch=getchar(); } return sum*f; } inline long long f(long long x){ long long res=sa; res=((res*x)%mode+sb)%mode; res=((res*x)%mode+sc)%mode; res=((res*x)%mode+sd)%mode; return res; } inline void prework(){ for (register long long i=2;i<=n;i++) a[i]=(f(a[i-1])+f(a[i-2]))%mode; } int main(){ freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); n=v_in(); sa=v_in(); sb=v_in(); sc=v_in(); sd=v_in(); a[0]=0; a[1]=v_in(); mode=v_in(); prework(); long long maxn=a[1],ans=0; for (long long i=2;i<=n;i++){ if (maxn<a[i]) maxn=a[i]; if (ans<maxn-a[i]) ans=maxn-a[i]; } if (ans&1) ans++; printf("%lld\n",ans>>1); return 0; } ``` ### travel[并查集] 0/100分。 并没有做这道题。 如果强行暴力的话可以60分。 然而正解是并查集。 我们只需要按照权值将询问和边从小到大排序 然后按顺序每次询问将权值小于该询问权值的边连起来合并即可。 ```cpp #include<cstdio> #include<algorithm> using namespace std; struct edge{ int u,v,w; bool operator < (const edge &k)const{ return w<k.w; } }e[200010]; struct query{ int x,w,id; bool operator < (const query &k)const{ return w<k.w; } }qu[100010]; int fa[100010],size[100010],ans[100010]; int n,m,q; inline int v_in(){ char ch=getchar(); int sum=0,f=1; while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ sum=(sum<<3)+(sum<<1)+(ch^48); ch=getchar(); } return sum*f; } inline int getf(int x){ if (fa[x]==x) return x; return fa[x]=getf(fa[x]); } inline void chain(int u,int v){ int f1=getf(u),f2=getf(v); if (f1!=f2){ fa[f2]=f1; size[f1]+=size[f2]; } } int main(){ freopen("travel.in","r",stdin); freopen("travel.out","w",stdout); n=v_in(); m=v_in(); q=v_in(); for (int i=1;i<=n;i++){ fa[i]=i; size[i]=1; } for (int i=1;i<=m;i++){ int u=v_in(),v=v_in(),w=v_in(); e[i].u=u; e[i].v=v; e[i].w=w; } sort(e+1,e+m+1); for (int i=1;i<=q;i++){ int x=v_in(),w=v_in(); qu[i].x=x; qu[i].w=w; qu[i].id=i; } sort(qu+1,qu+q+1); int pos=1; for (int i=1;i<=q;i++){ while (e[pos].w<=qu[i].w&&pos<=m){ chain(e[pos].u,e[pos].v); pos++; } ans[qu[i].id]=size[getf(qu[i].x)]; } for (int i=1;i<=q;i++) printf("%d\n",ans[i]); return 0; } ``` ### string[KMP] 这个题因为不会~~看毛片~~所以不会做。 然后就暴力了50/100分。 其实这题是很裸的一道KMP 求出匹配数=x ```cpp #include<cstdio> #include<cstring> int k,n,ans,next[5010]; char s[5010]; void kmp(int pos){ for (int i=1;i<=n;i++) next[i]=pos-1; for (int i=pos+1;i<=n;i++){ int j=next[i-1]; while (j!=pos-1&&s[j+1]!=s[i]) j=next[j]; if (s[j+1]==s[i]) j++; next[i]=j; } int j=next[pos]; for (int i=pos+1;i<=n;i++){ while (j!=pos-1&&s[j+1]!=s[i]) j=next[j]; if (s[j+1]==s[i]) j++; while ((j-pos+1)*2>=i-pos+1) j=next[j]; if (j-pos+1>=k) ans++; } } int main(){ freopen("string.in","r",stdin); freopen("string.out","w",stdout); scanf("%s",s+1); scanf("%d",&k); n=strlen(s+1); for (int i=1;i<=n;i++) kmp(i); printf("%d\n",ans); return 0; } ``` ans+=x\*(x+1)/2 所以说呢,我其实基本功还是不过关的。 如果说最优状态的话,我估计可以拿到260分左右。 第二题暴力骗60,其他裸题,不出差错就有260分。 最终只有一百分。我好菜啊。 ## 2.kmp真是玄学啊 我今天重新复习了一边kmp,看了一个写的很好的博客 然后就觉得kmp这种算法真的是优化了很多,节约了很多时间 比起暴力o(nm),kmp只需要o(n+m) 在这里贴个[链接](http://blog.csdn.net/v\_JULY\_v/article/details/7041827) ## 3.还有需要弄的内容 (1) 白书4.1~4.5(一个星期弄完) (2) kmp复习 (3) 计算几何(扫描线&&凸包)