2019.9.15 NOIP模拟测试

没有来考,现在补上。

T1:passward

 

 其实一看肯定就会想到kmp,但是我一开始思路是错的,只有六十分。(本来这题数据就很水)

后来调了一下,还是就过了。

题解:

首先我们就将密码串进行自我匹配然后求出fail数组的值。然后就从尾部跳fail指针,跳到每一个前缀上,然后用这个前缀来匹配,如果这个匹配串在模式串中出现了超过3次(前缀,后缀,中间),那么就证明是可行的。由于数据太水,这样还不会被卡到n方,如果出现像aaaaaaaaaaaaaaa这样的字符串,那我的这个算法就死了。基本上是接近o(n)的复杂度。然后最后我们直接就输出第一次找到的符合条件的子串,因为后面越来越短。

 

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
char s[maxn];
int st,ed;
int lenn,len;
int fail[maxn];
char newchar[maxn];
int ans;
int id;
int l[maxn],r[maxn];
void getfail(){
    fail[1]=fail[0]=0;
    int j=0;
    for(int i=2;i<=len;i++){
        while(j!=0&&s[i]!=s[j+1]) j=fail[j];
        if(s[i]==s[j+1]) j++;
        fail[i]=j;
    }
}
void kmp(){
    int j=0;
    ans=0;
    for(int i=1;i<=len;i++){
        while(j!=0&&s[i]!=newchar[j+1]) j=fail[j];
        if(s[i]==newchar[j+1]) j++;
        if(j==lenn) ans++;
    }
}
int main(){
    scanf("%s",s+1);
    len=strlen(s+1);
    getfail();
    st=1,ed=len;
    while(fail[ed]){
        lenn=0;
        memset(newchar,0,sizeof(newchar)); 
        for(int i=1;i<=fail[ed];i++){
            newchar[++lenn]=s[i];
        }
        kmp();
        if(ans>=3) l[++id]=1,r[id]=fail[ed];
        ed=fail[ed];
    }
    if(!id) printf("Just a legend\n"); 
    for(int i=l[1];i<=r[1];i++) printf("%c",s[i]);
    return 0;
}
View Code

 

T2 So

 

40分的dp还是好写,设dp[i][j]表示到第i个数时选了j个数。

但是数据范围显然不允许我们这样做。

这道题有一个难点就是维护这个数相邻的两个数的位置,用最简单的链表即可。

参考题解的做法,我们在贪心的时候就用一个集合来维护。因为集合已经帮你排好序了。

但考虑反悔的情况,比如我们先选了A,但是如果之后B+C更优的话怎么办呢,那么就在集合中删除B,C,插入一个B+C-A,如果发现此解更优的话就会把它给选了。

最后还要注意合并。

推荐:

双倍经验:

P1484 种树

P1792 [国家集训队]种树

代码如下:

 

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
#define inf (long long)(1<<62);
struct node{
    long long val;
    int pp;
    node(){
    
    }
    node(long long va,int p){
        val=va;
        pp=p;
    }
    friend bool operator <(const node &a,const node &b){
        return (a.val==b.val)?(a.pp>b.pp):(a.val>b.val);
    }
};
set<node>s;
int pre[maxn],nxt[maxn],n,k;
long long a[maxn];
long long ans;
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        pre[i]=i-1;
        nxt[i]=i+1;
        s.insert(node(a[i],i));
    } 
    a[0]=-1e15;
    nxt[n]=0;
    while(k--){
        int now=s.begin()->pp;
        ans+=a[now];
        a[now]=-a[now];
        a[now]+=a[pre[now]];
        a[now]+=a[nxt[now]];
        s.erase(s.begin());
        s.erase(node(a[pre[now]],pre[now]));
        s.erase(node(a[nxt[now]],nxt[now]));
        s.insert(node(a[now],now));
        if(pre[pre[now]]) nxt[pre[pre[now]]]=now;
        if(nxt[nxt[now]]) pre[nxt[nxt[now]]]=now;
        pre[now]=pre[pre[now]];
        nxt[now]=nxt[nxt[now]];
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

T3 留坑代填

 

posted @ 2019-09-16 19:56  JBLee  阅读(185)  评论(0编辑  收藏  举报