「持续更新」经典食谱

2020.1.25

luoguOJ-P3796 【模板】AC自动机(加强版)

\(WA\) 穿原因:对于 \(trie\) 树的数组大小有问题——数组开小


2020.1.31

CF-1031D Minimum path

样例没过原因

对于 \(ans\) 数组的初始化应该在 \(1\)\(2n\) 这段,但是我只初始化到 \(n\) ,也就是

rep(i,0,n<<1)ans[i]=maxchar;

我给写成了

rep(i,0,n)ans[i]=maxchar;

\(WA\space on \space test\space 6\)

缺少了特判——当整条路可以直接全部改为 \(a\) 的时候我没判(但从理论上说不是应该可以的吗?)

少打了这一段

if(Num[n][n]<=k){
    rep(i,1,n*2-1)putchar('a');
    return;
}

2020.2.2

CF-1019A

\(RE\) 原因

在这段代码中:

len=vote[j].size()-i+1,ind=0;

因为 vote[j].size()ungisned int 类型,所以如果它被减成负数将会变成一个极大值,所以应该这样写:

len=(int)vote[j].size()-i+1,ind=0;

2020.2.9

CF-909E-Coprocessor

\(WA\) 穿原因

先尽量处理主任务管理器的任务,这样可以让子管理器一次性尽可能多的处理任务,也就是两个队列的处理要这样打:

while(!(Q[0].empty() && Q[1].empty())){
    while(!Q[0].empty()){
        u=Q[0].front();Q[0].pop();
        for(int i=tail[u],v;i;i=e[i].nxt){
            if(!--in[v=e[i].to])Q[mch[v]].push(v);
        }
    }
    if(!Q[1].empty())++ans;//开机一次
    while(!Q[1].empty()){
        u=Q[1].front();Q[1].pop();
        for(int i=tail[u],v;i;i=e[i].nxt){
            if(!--in[v=e[i].to])Q[mch[v]].push(v);
        }
    }
}

内部的两个 while() 位置切莫调换!

2020.5.18

[FJOI2015]火星商店问题

过不了样例,差点自闭,最后发现:

if(trie[trie[rt1].son[!f]].siz<trie[trie[rt2].son[!f]].siz){
    // printf("Goto way !f == %d\n",!f);
    ret+=(i<<1);
    rt1=trie[rt1].son[!f],rt2=trie[rt2].son[!f];
}else rt1=trie[rt1].son[f],rt2=trie[rt2].son[f];

这段代码中第三行——1<<i 打成 i<<1

似乎很多次犯过这样的错,需要注意了。

感到不妙了

2020.5.30

[Code+#2]火锅盛宴

关于 set 的去重问题。

假设我们定义了一个 set<node>s,对于结构体 node 我们重载其 < 运算。

那么,如果 set 中的两个元素 \(a,b\),假如他们在我们重载或者定义的优先级比较之下,同时不满足 \(a<b\)\(b<a\),那么就会判定 \(a\)\(b\)等价的,这个时候 set 就会去重。举个栗子:

struct node{int t,id;
    bool operator <(const node rhs)const{
        return t<rhs.t;
    }
};
set<node>a;

那么,在 set 的去重中,只要满足某两个元素的 \(t\) 是一样的,set 就会认定他们是同一元素并去重,而不会在意 \(id\) 是否是相同的。

所以我这道题 WA 穿了**

2020-6-4

关于 vector 的储存问题

在这样一种情况下:

vector<int>v;
int test(){
    v.resize(1000);
    return 1;
}
int main(){
    v.resize(5);
    v[1]=test();
}

是会 RE 的,但是原因?

因为 vectorresize() 是会更改内存地址的,但是 vector= 赋值原理是先取出要赋值的元素地址(例子中即 v[1] 的地址),在执行完函数 test() 之后对这个地址进行赋值,但是在 test() 中,由于 resize() 更改了地址,这个时候在之前取出来的 v[1] 的地址已经变成一个野生地址,再执行赋值就会 RE

CF-246E Blood Cousins Return

这道题为什么要开两倍空间?

是因为下面的代码块中的第二行,由于 \(q[u].back().d\le n,d\le n\),故加起来可能会超过 \(n\),所以开两倍空间。

更好的解决办法,加一个 if 特判一下即可。

while(!q[u].empty()){
    ans[q[u].back().i]=cnt[q[u].back().d+d].size();
    q[u].pop_back();
}

2020-7-27

用桶进行哈希时的一些注意事项

错例:传送门

从桶出来,将原数组变为哈希值时,注意本题 \(a\) 的取值范围 \(0\le a_i\le 1000\),故下面的循环:

rep(i,0,MAXN)if(t[i]){
    a[++k]=i-n;
    if(a[k]==0){writc(1,'\n');exit(0);}
    if((a[k]<0 && sign==1) || (a[k]>0 && sign==-1)){
        flg=false;
    }
    if(a[k]<0)sign=-1;
    else sign=1;
}

\(i\) 必须从 \(0\)\(1000\) 进行枚举,而非错例中的 \(1\)\(1000\)

2020-7-29

关于 \(RE\) 的一些建议...

注意数组定义时使用的 MAXNMAXM,这俩东西有点像...

2020-8-18

关于 \(lca\) 代码简化的一些思路 bug

求树上两点间最大边权,试试下面这段代码:

inline int Query_Max(int u,int v){
    int ret=0;
    if(dep[u]<dep[v])swap(u,v);
    update(u,dep[v],ret);
    if(u==v)return ret;
    fep(j,logmaxn,0)if(f[u][j]!=f[v][j] || j==0){
        ret=Max(ret,Max(maxx[u][j],maxx[v][j]));
        u=f[u][j],v=f[v][j];
        if(u==v)break;
    }
    return ret;
}

感觉 if 中的 j==0 十分巧妙,因为把最后一步两点跳到 \(lca\) 同时处理到了,但是并没有意识到 \(u,v\) 在跳完 \(j==0\) 这一步之后距离 \(lca\) 还差 \(1\) 步,这个思路就少跳了一步,所以应该这样写

inline int Query_Max(int u,int v){
    int ret=0;
    if(dep[u]<dep[v])swap(u,v);
    update(u,dep[v],ret);
    if(u==v)return ret;
    fep(j,logmaxn,0)if(f[u][j]!=f[v][j]){
        ret=Max(ret,Max(maxx[u][j],maxx[v][j]));
        u=f[u][j],v=f[v][j];
        if(u==v)break;
    }
    ret=Max(ret,Max(maxx[u][0],maxx[v][0]));
    return ret;
}

2020-10-24

SGU183 Painting the balls

失踪人口回归

有一个类似于滚动的数组,它的转移是这样的:

const int maxm=100;
inline void Get_f(){
    memset(f,0x3f,sizeof f);
    rep(i,1,m)rep(j,1,i-1)f[i][j]=c[i]+c[j];
    int minn;
    rep(j,1,n-1){minn=inf;
        fep(i,Min(j+m-1,n),j+1){if(i<=m)break;
            minn=Min(minn,f[j%maxm][(i-m)%maxm]);
            f[j%maxm][(i-m)%maxm]=inf;
            f[i%maxm][j%maxm]=minn+c[i];
        }
    }
    int ans=inf;
    rep(i,n-m,n)rep(j,n-m,i-1)ans=Min(ans,f[i%maxm][j%maxm]);
    cout<<ans<<'\n';
}

但是这个 maxm 不能准确地赋值为 \(100\),因为我们用的是取模,这样做会见一些状态(比如 \(m\) 刚好为 \(100\))的情况弄掉了.

所以至少也得弄个 \(101\).

2021-2-6

BZOJ3218 a + b Problem

这个问题直接调俩晚上......

写线段树的时候,如果要传参,像这样:

void query(const int L,const int R,const int p,const int i,const int l=0,const int r=maxa)

要注意线段树维护的数据的范围,比如这里 \(a\)非负整数,所以 \(l\) 要从 \(0\) 开始......

posted @ 2020-01-25 21:24  Arextre  阅读(625)  评论(0编辑  收藏  举报