• 6/14考试总结


    实锤:我就是一个超级大垃圾!!!

    必须从这个视角俯瞰自己了啊

    T1:Censoring

    FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过1e5的字符串S。他有一个包含n个单词的列表,列表里的n个单词记为ti,他希望从S中删除这些单词。
    FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词
    FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的
    请帮助FJ完成这些操作并输出最后的S。第一行包含一个字符串S
    第二行包含一个整数N N<2000 接下来的N行,每行包含一个字符串i​​1​​...tNt_NtN​​。他希望从S中删除这些单词。
    FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词
    FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的
    请帮助FJ完成这些操作并输出最后的S
    5​​的字符串S。他有一个包含n个单词的列表,列表里的n个单词记为t1t_1t1​​...tNt_NtN​​。他希望从S中删除这些单词。
    FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词
    FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的
    请帮助FJ完成这些操作并输出最后的S

    一本通水题,AC自动机+栈,hash也能过,过多的回溯fail指针导致T,40。

    AC自动机尝试匹配时需要通过fail指针进行回溯,所以在开始匹配前处理好结束标记就行。

    利用好数组模拟栈的特性,不要一个一个pop。

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 char s[100005],word[100005];
     5 int n,cnt,last[100005],bj[100005],t[100005][26],fail[100005],fin[100005];
     6 int q[100005],q1,q2,leng,stack[100005],top;
     7 void insert(char *ss){
     8     int p=0,len=strlen(ss);
     9     for(int i=0;i<len;++i)
    10         if(t[p][ss[i]-'a'])p=t[p][ss[i]-'a'];
    11         else p=t[p][ss[i]-'a']=++cnt;
    12     fin[p]=len;
    13 }
    14 void bfs(){
    15     q1=1;for(int i=0;i<=25;++i)if(t[0][i])q[++q2]=t[0][i];
    16     for(;q1<=q2;++q1)for(int i=0;i<=25;++i)
    17         if(t[q[q1]][i])fail[q[++q2]=t[q[q1]][i]]=t[fail[q[q1]]][i];
    18         else t[q[q1]][i]=t[fail[q[q1]]][i];
    19 }
    20 void find(){
    21     int p=0,k;
    22     for(int i=0;i<leng;++i){
    23         k=last[i]=p=t[p][s[i]-'a'];stack[++top]=i;
    24         while(k){
    25             if(fin[k]){
    26                 p=last[stack[top-fin[k]+1]-1];
    27                 for(int ii=1;ii<=fin[k];++ii)bj[stack[top]]=1,top--;
    28                 break;
    29             }
    30             k=fail[k];
    31         }
    32     }
    33 }
    34 int main(){
    35     //freopen("cen.in","r",stdin);
    36     //freopen("cen.out","w",stdout);
    37     scanf("%s%d",s,&n);leng=strlen(s);
    38     for(int i=1;i<=n;++i)scanf("%s",word),insert(word);
    39     bfs();find();
    40     for(int i=0;i<leng;++i)if(!bj[i])putchar(s[i]);
    41 }
    考场错解
     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 char s[100005],word[100005];
     5 int n,cnt,last[100005],bj[100005],t[100005][26],fail[100005],fin[100005];
     6 int q[100005],q1,q2,leng,stack[100005],top;
     7 void insert(char *ss){
     8     int p=0,len=strlen(ss);
     9     for(int i=0;i<len;++i)
    10         if(t[p][ss[i]-'a'])p=t[p][ss[i]-'a'];
    11         else p=t[p][ss[i]-'a']=++cnt;
    12     fin[p]=len;
    13 }
    14 void bfs(){
    15     q1=1;for(int i=0;i<=25;++i)if(t[0][i])q[++q2]=t[0][i];
    16     for(;q1<=q2;++q1)for(int i=0;i<=25;++i)
    17         if(t[q[q1]][i])fail[q[++q2]=t[q[q1]][i]]=t[fail[q[q1]]][i];
    18         else t[q[q1]][i]=t[fail[q[q1]]][i];
    19 }
    20 void find(){
    21     int k=0;
    22     for(int i=0;i<leng;++i){
    23         k=last[i]=t[k][s[i]-'a'];stack[++top]=i;
    24         if(fin[k]){
    25             top-=fin[k];
    26             k=last[stack[top]];
    27             
    28         }
    29     }
    30 }
    31 int main(){
    32     scanf("%s%d",s,&n);leng=strlen(s);
    33     for(int i=1;i<=n;++i)scanf("%s",word),insert(word);
    34     bfs();find();
    35     for(int i=1;i<=top;++i)putchar(s[stack[i]]);
    36 }
    考后正解(4次修改)

    T2:记忆的轮廓

    一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增,在[1,n]中,一共有n个节点。我们把编号在[1,n]的叫做正确节点,[n+1,m]的叫做错误节点。一个叶子,如果是正确节点则为正确叶子,否则称为错误叶子。莎缇拉要帮助昴到达贤者之塔,因此现在面临着存档位置设定的问题。
    为了让昴成长为英雄,因此一共只有p次存档的机会,其中1和n必须存档。被莎缇拉设置为要存档的节点称为存档位置。当然不能让昴陷入死循环,所以存档只能在正确节点上进行,而且同一个节点不能存多次档。因为通往贤者之塔的路上有影响的瘴气,因此莎缇拉假设昴每次位于树上一个节点时,都会等概率选择一个儿子走下去。每当走到一个错误叶子时,再走一步就会读档。具体的,每次昴到达一个新的存档位置,存档点便会更新为这个位置(假如现在的存档点是i,现在走到了一个存档位置j>i,那么存档点便会更新为j)。读档的意思就是回到当前存档点。初始昴位于1,当昴走到正确节点n时,便结束了路程。莎缇拉想知道,最优情况下,昴结束路程的期望步数是多少?50<=p<=n<=700,m<=1500,T<=5。数据保证每个正确节点均有至少2个儿子,至多3个儿子。

    全场爆零,数据范围没粘梯度,50%很好拿的也没人拿到,而我有看错了题目,0。

    考场上其实已经想到了70%思路,但毕竟读错题了。

    其中一种正解很抖机灵,存档点相距太远答案就会爆炸增长而存档机会又不少,设不会在相距40以上的点存档,就能把70变成AC

    题解也有很多种,每种都值得学习。

     1 #include<cstdio>
     2 int n,m,p,ext[705],a,t,b;
     3 double times[705],dt[705][705],dp[705][705];
     4 inline double min(double a,double b){return a<b?a:b;}
     5 int main(){
     6     //freopen("memory.in","r",stdin);
     7     //freopen("memory.out","w",stdout);
     8     scanf("%d",&t);
     9     while(t--){
    10         scanf("%d%d%d",&n,&m,&p);
    11         for(int i=1;i<=n;++i)ext[i]=0;
    12         for(int i=1;i<=m-n;++i){
    13             scanf("%d%d",&a,&b);
    14             if(a<=n)ext[a]++;
    15             if(b<=n)ext[b]++;
    16         }
    17         for(int i=1;i<=n;++i)ext[i]++;
    18         for(int i=2;i<=n;++i){
    19             times[i]=1;
    20             for(int j=i-1;j;--j)
    21                 times[j]=times[j+1]*ext[j],dt[j][i]=dt[j+1][i]+times[j]/ext[j]+times[j]*2*(ext[j]-1)/ext[j];
    22         }
    23         for(int i=1;i<=700;++i)for(int j=1;j<=700;++j)dp[i][j]=1e10;
    24         dp[1][1]=0;
    25         for(int i=1;i<n;++i)for(int j=1;j<=i;++j)for(int k=i+1;k<=n;++k)dp[k][j+1]=min(dp[k][j+1],dp[i][j]+dt[i][k]);
    26         printf("%.4lf",dp[n][p]);
    27     }
    28     
    29 }
    考场错解
     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 #define mm(a) memset(a,0,sizeof(a))
     5 int n,m,p,a,b,t;double dt[1505][1505],g[1505],tot[1505],dp[1505][1505];int fir[1505],to[1530],l[1530],cnt,s[1505];
     6 inline double min(double a,double b){return a<b?a:b;}
     7 void connect(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
     8 void dfs(int p){dt[p][p]=0;
     9     for(int i=fir[p];i;i=l[i]){
    10         dfs(to[i]),s[p]++;
    11         if(p>n)g[p]+=g[to[i]];
    12     }
    13     if(p>n)if(s[p])g[p]=g[p]/s[p]+1;else g[p]=1;
    14     if(p<=n)for(int i=fir[p];i;i=l[i])tot[p]+=g[to[i]];
    15 }
    16 int main(){//freopen("1.in","r",stdin);
    17     scanf("%d",&t);
    18     while(t--){
    19         scanf("%d%d%d",&n,&m,&p);
    20         cnt=0;mm(tot);mm(g);mm(s);mm(fir);
    21         for(int i=1;i<=n;++i)for(int ap=1;ap<=p;++ap)dp[i][ap]=1e20;dp[1][1]=0;
    22         for(int i=1;i<=m-n;++i)
    23             scanf("%d%d",&a,&b),connect(a,b);
    24         for(int i=1;i<n;++i)connect(i,i+1);
    25         dfs(1);
    26         for(int i=1;i<=n;++i)
    27             for(int j=i+1;j<=i+40&&j<=n;++j)
    28                 dt[i][j]=dt[i][j-1]*s[j-1]+s[j-1]+tot[j-1];
    29         for(int i=2;i<=n;++i)
    30             for(int j=((i-40>=1)?i-40:1);j<i;++j)
    31                 for(int ap=2;ap<=i;++ap)
    32                     dp[i][ap]=min(dp[i][ap],dp[j][ap-1]+dt[j][i]);
    33         printf("%.4lf
    ",dp[n][p]);
    34     }
    35 }
    考后正解(6次修改)

    T3:雨天的尾巴

    N个点,形成一个树状结构。有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成所有发放后,每个点存放最多的是哪种物品。

    1<=N,M<=100000,1<=a,b,x,y<=N,1<=z<=1e99​​

    树上权值线段树动态开点+树上差分,考场上想出了树上差分可是不会弄,纯暴力50。

    差分是从下往上,不是从根往下捯!这回彻底记住了。

    改的时候线段树合并打错。。。忘了直接继承节点了而是此次都新建,M->R->M->R...

     1 #include<cstdio>
     2 #include<map>
     3 using namespace std;
     4 int f[5001][13],fir[5001],l[10001],to[10001],cnt,dep[10001],res;
     5 int ta[100001],tb[100001],tk[100001],lwb[5001],kind,a,b,LCA,n,mm;
     6 int have[5001][5001],ref[5001];
     7 map<int,int>m;
     8 void connect(int a,int b){
     9     l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;
    10     l[++cnt]=fir[b];fir[b]=cnt;to[cnt]=a;
    11 }
    12 void dfs(int p){
    13     for(int i=1;i<=12;++i)f[p][i]=f[f[p][i-1]][i-1];
    14     for(int i=fir[p];i;i=l[i])if(to[i]!=f[p][0])f[to[i]][0]=p,dep[to[i]]=dep[p]+1,dfs(to[i]);
    15 }
    16 int lca(int a,int b){
    17     if(dep[a]<dep[b])res=a,a=b,b=res;
    18     for(int dt=dep[a]-dep[b];dt;dt-=dt&-dt)a=f[a][lwb[dt&-dt]];
    19     if(a==b)return a;
    20     for(int i=12;i>=0;--i)if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i];
    21     return f[a][0];
    22 }
    23 int main(){
    24     //freopen("tail.in","r",stdin);
    25     //freopen("tail.out","w",stdout);
    26     for(int i=0;i<=12;++i)lwb[1<<i]=i;
    27     scanf("%d%d",&n,&mm);
    28     for(int i=1;i<n;++i)scanf("%d%d",&a,&b),connect(a,b);
    29     for(int i=1;i<=mm;++i){
    30         scanf("%d%d%d",&ta[i],&tb[i],&tk[i]);
    31         if(m.find(tk[i])==m.end())m[tk[i]]=++kind,ref[kind]=tk[i];
    32         tk[i]=m[tk[i]];
    33     }
    34     dfs(1);
    35     for(int i=1;i<=mm;++i){
    36         LCA=lca(ta[i],tb[i]);
    37         for(int ii=ta[i];ii!=LCA;ii=f[ii][0])have[ii][tk[i]]++;
    38         for(int ii=tb[i];ii!=LCA;ii=f[ii][0])have[ii][tk[i]]++;
    39         have[LCA][tk[i]]++;
    40     }
    41     for(int i=1;i<=n;++i){
    42         int ans=0;
    43         for(int j=1;j<=kind;++j)if(have[i][j]>have[i][ans]||(have[i][j]==have[i][ans]&&ref[j]<ref[ans]))ans=j;
    44         printf("%d
    ",ref[ans]);
    45     }
    46 }
    考场错解
     1 #include<cstdio>
     2 #include<map>
     3 #include<algorithm>
     4 using namespace std;
     5 inline int max(int a,int b){return a>b?a:b;}
     6 int f[100001][19],fir[100001],l[200001],to[200001],cntt,dep[100001],res;
     7 int ta[100001],tb[100001],tk[100001],lwb[300001],kind,a,b,LCA,n,mm;
     8 int ref[100001],ans[100001];
     9 int w[15000000],lc[15000000],rc[15000000],cnt=100000;
    10 int bf[100001];
    11 map<int,int>m;
    12 void connect(int a,int b){
    13     l[++cntt]=fir[a];fir[a]=cntt;to[cntt]=b;
    14     l[++cntt]=fir[b];fir[b]=cntt;to[cntt]=a;
    15 }
    16 void dfs(int p){
    17     for(int i=1;i<=18;++i)f[p][i]=f[f[p][i-1]][i-1];
    18     for(int i=fir[p];i;i=l[i])if(to[i]!=f[p][0])f[to[i]][0]=p,dep[to[i]]=dep[p]+1,dfs(to[i]);
    19 }
    20 int lca(int a,int b){
    21     if(dep[a]<dep[b])res=a,a=b,b=res;
    22     for(int dt=dep[a]-dep[b];dt;dt-=dt&-dt)a=f[a][lwb[dt&-dt]];
    23     if(a==b)return a;
    24     for(int i=18;i>=0;--i)if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i];
    25     return f[a][0];
    26 }
    27 void add(int &p,int l,int r,int pos,int ww){
    28     if(!p)p=++cnt;
    29     if(l==r){w[p]+=ww;return;}
    30     int mid=l+r>>1;
    31     if(pos>mid)add(rc[p],mid+1,r,pos,ww);
    32     else add(lc[p],l,mid,pos,ww);
    33     w[p]=max((lc[p]?w[lc[p]]:0),(rc[p]?w[rc[p]]:0));
    34 }
    35 int find_ans(int p,int l,int r){
    36     if(!w[p])return 0;
    37     if(l==r)return l;
    38     int mid=l+r>>1;
    39     if(lc[p]&&w[p]==w[lc[p]])return find_ans(lc[p],l,mid);
    40     else return find_ans(rc[p],mid+1,r);
    41 }
    42 void merge(int p,int l,int r,int &fa){
    43     int mid=l+r>>1;if(!fa)fa=++cnt,printf("%d %d %d %d
    ",p,l,r,cnt);
    44     if(l==r){w[fa]+=w[p];return;}
    45     if(lc[p])if(lc[fa])merge(lc[p],l,mid,lc[fa]);else lc[fa]=lc[p];
    46     if(rc[p])if(rc[fa])merge(rc[p],mid+1,r,rc[fa]);else rc[fa]=rc[p];
    47     w[fa]=max((lc[fa]?w[lc[fa]]:0),(rc[fa]?w[rc[fa]]:0));
    48 }
    49 void dfs_ans(int p){
    50     for(int i=fir[p];i;i=l[i])if(to[i]!=f[p][0])dfs_ans(to[i]);
    51     ans[p]=find_ans(p,1,kind);if(f[p][0])merge(p,1,kind,f[p][0]);
    52 }
    53 int main(){
    54     for(int i=0;i<=18;++i)lwb[1<<i]=i;
    55     scanf("%d%d",&n,&mm);
    56     for(int i=1;i<n;++i)scanf("%d%d",&a,&b),connect(a,b);
    57     for(int i=1;i<=mm;++i)scanf("%d%d%d",&ta[i],&tb[i],&tk[i]),bf[i]=tk[i];
    58     sort(bf+1,bf+1+mm);
    59     for(int i=1;i<=mm;++i)if(m.find(bf[i])==m.end())m[bf[i]]=++kind,ref[kind]=bf[i];
    60     for(int i=1;i<=mm;++i)tk[i]=m[tk[i]];
    61     dfs(1);
    62     for(int i=1;i<=mm;++i){
    63         LCA=lca(ta[i],tb[i]);
    64         add(ta[i],1,kind,tk[i],1);add(tb[i],1,kind,tk[i],1);
    65         add(LCA,1,kind,tk[i],-1);add(f[LCA][0],1,kind,tk[i],-1);
    66     }
    67     dfs_ans(1);
    68     for(int i=1;i<=n;++i)printf("%d
    ",ref[ans[i]]);
    69 }
    考后正解(23次修改)

    你很弱诶,你真的很弱诶。啥都不会打,暴力骗分总分还干不过T1一个hash。

    考场上心态太自信了吧,T1打完过样例之后又手模了4,5组都没问题。就往后走了

    T2,T3寻思着T1应该稳了,100分rank也不低就飘了。

    平时打代码要注重理解。。。不要着急赶进度,注重积累,记住每一个小知识点,谁知道什么时候会有用

    难题可以不打,简单题必须AC,暴力对拍检查低错,先稳后强。

    加油吧,还有机会,小心被干到第二机房。

  • 相关阅读:
    Distributing Jython Apps in a Single JAR file
    Installing Jython and Django Sun GlassFish Enterprise Server v3 Scripting Framework Guide
    使用FILE
    C array length example
    package jruby gems in one jar for embedded used in java
    Hypertext Transfer Protocol HTTP/1.1
    jruby gems
    安装jruby和rails,创建 application ITeye技术网站
    RichTextBox
    【C语言】getchar函数的控制台输入原理,回车符的处理
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11057937.html
Copyright © 2020-2023  润新知