NOIP游寄

· · 个人记录

某种意义来说,玩的开心即为 AK。热烈庆祝 CHiCO 阿克 NOIP!

开考前一周,我给学弟讲离线扫描线。

提前三天入佛隔离。

在佛山复习了 tarjan 和 笛卡尔树。同宿的老炮一直和我讲 dp 和 计数 思路。

比赛队里有一个初三的,一问发现比我大 20 天。

不得不说玩的很开心。

这次比赛有幸毫无遗憾。

这次比赛允许带水:感天动地。

密码:biu#2019miss,solo@2022(应该吧,我不太记得了。

开看题:T1 不会;T2 不会;T3 不会;T4 不会;

首先胡乱到处想:T1 不会计数;T2 不会思维;T3 不会计数;T4 不会计数。

浅想一手:

T3 有链的分,有树的分,很明显 tarjan 把环缩了做树形 dp。正好复习了,可是不会计数。

T4 一看就是数据结构。min/max 感觉像 笛卡尔树,数据随机相当于笛卡尔树树高 log。但是在线确实想不出来,又没有强制在线,那就离线吧!但思维确实跟不上,不会计数,寄!

虽然非常不情愿,但是只能想 T2 了。

k=2n-2 很有意思,一看就是放两层,最后一个用来消除。(但是只有15 pts。

想了一会怎么找到,结果发现不好分配位置和查找在第几层。强行抑制住打平衡树的冲动,冷静一会发现可以 stack 分配位置,桶 查找。

打完跑去 T1,对着一堆求和弄了半天,发现可以前缀和优化一下。最开始是正序循环,结果代码越打越乱,跑去想 T2。

发现 k=2n-1 也可以套一套之前的想法,并且发现之前想法的 bug,稍稍改了改。

跑去看 T4,发现可能可以用单调栈代替一手,思考半天完全想不出来,n^2 个区间让我怎么理智!打个 8pts 暴力跑路。

在看 T1,换成倒序循环,结果代码简单多了,心情瞬间舒畅。

测大样例,看着那个 114 514 想骂人:谁大数据给那么水的东西啊。

回去 T2,发现可以把多出来的颜色待定,先考虑后面的,根据后面的卡牌决定这个卡牌的位置。

  1. 从上面消除的肯定不能放。
  2. 如果从下面消除的,可以把它放在上面,这样高度还是 2 层。
  3. 如果有一列直接消没了,那么可以大胆放在空列里,让新消的变成空列。
  4. 其他照常。

但是这有一个问题:有可能全部都是消上层,最后只能放在空列,变成 n 个 1 层。这样可能就无解了。感觉自己的做法寄了。(后面想了想发现没寄:最后总有一个多出来的颜色,消上面的不用管,消下面的就让前面的放置第 2 层避开就行了。估计就这一个问题,差点想出来……

bug 有点小多,改到心理崩溃。

后面就是测大样例,不给 spj 我测个毛线啊!

随意构造几组数据,貌似都是对的。

然后想 T3:n=8,m=10 应该是状压分,但是脑子抽了以为 2^8 是 10^6,痛失暴力分。(其实也不算痛失,我也不熟状压。

最后写了个随机数输出,用于碰彩票。

后面想 T4,一脸懵逼地等到考试结束。

难得一次复习的东西都考了,猜知识点很对,但不完全对。(笑

人均切 T2 T3,完全不明白好吧。

心疼 BOBO,初中两次摸到 NOIP 一等线,这次却失手了。

回来还要在家隔离,还有重要考试要考。。。能不能退钱?(貌似没钱可退

期望得分:100+15+0+8=123

放出代码,看看有没有刺可以挑挑:

T1:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1e3+10,mod=998244353;
int a[N][N],b[N][N],c[N][N];
long long d[N][N],e[N][N];
string s;
int main(){
    freopen("plant.in","r",stdin);
    freopen("plant.out","w",stdout);
    int t,id;cin>>t>>id;
    while(t--){
        int n,m,k,l;cin>>n>>m>>k>>l;
        for(int i=1;i<=n;i++){
            cin>>s;
            for(int j=1;j<=m;j++)
                a[i][j]=s[j-1]-'0';
        }
        for(int i=1;i<=n;i++){
            for(int j=m;j>=1;j--){
                if(a[i][j]) continue;
                b[i][j]=b[i][j+1]+1;
            }
        }
        for(int j=1;j<=m;j++){
            for(int i=n;i>=1;i--){
                if(a[i][j]) continue;
                c[i][j]=c[i+1][j]+1;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(b[i][j]) b[i][j]--;
                if(c[i][j]) c[i][j]--;
            }
        }
        for(int j=1;j<=m;j++){
            for(int i=n;i>=1;i--){
                if(a[i][j]||c[i][j]<=1) continue;
                d[i][j]=(d[i+1][j]+b[i+2][j])%mod;
                if(c[i][j]<=2) continue;
                e[i][j]=(e[i+1][j]+b[i+2][j]*(c[i][j]-2)%mod)%mod;
            }
        }
        long long a1=0,a2=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(a[i][j]) continue;
                a1=(a1+b[i][j]*d[i][j]%mod)%mod;
                a2=(a2+b[i][j]*e[i][j]%mod)%mod;
            }
        cout<<k*a1<<' '<<l*a2<<'\n';
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                a[i][j]=b[i][j]=c[i][j]=d[i][j]=e[i][j]=0;
    }
}
/*
1 0
4 3 1 1
001
010
000
000
*/

T2:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=2e6+10;
struct node{
    int opt,s1,s2;
};
node ans[2*N];
int a[N],b[3][N],c[N],d[3][N];
int sta[2*N],top,cnt;
int n,m,k,num;
inline int chk(int x){
    if(b[1][x]) return 1;
    else if(b[2][x]) return 2;
    else return 0;
}
inline int fnd(int opt,int x){
    return b[opt][x];
}
int work(int p){
    int now=++cnt;
    for(int i=p+1;i<=m;i++){
        int opt=chk(a[i]),pos;
        if(opt) pos=fnd(opt,a[i]);
        if(a[i]==a[p]){
            ans[now].opt=1,ans[now].s1=num;
            cnt++;ans[cnt].opt=1,ans[cnt].s1=num;
            return i;
        }
        else if(opt==2&&c[pos]==1){
            ans[now].opt=1,ans[now].s1=num;
            sta[++top]=pos,c[pos]--;
            b[2][a[i]]=0,d[2][pos]=0;
            cnt++;ans[cnt].opt=1,ans[cnt].s1=pos;
            num=pos;
            return i;
        }
        else if(opt==1){
            sta[++top]=pos,c[pos]--;
            b[1][a[i]]=0,d[1][pos]=0;
            cnt++;ans[cnt].opt=1,ans[cnt].s1=pos;
        }
        else if(opt==2){
            sta[++top]=pos;
            b[2][a[i]]=0,d[2][pos]=d[1][pos];
            d[1][pos]=a[p],b[1][d[2][pos]]=0;
            b[2][d[2][pos]]=pos;
            b[1][a[p]]=pos;
            ans[now].opt=1,ans[now].s1=pos;
            cnt++;ans[cnt].opt=1,ans[cnt].s1=num;
            cnt++;ans[cnt].opt=2,ans[cnt].s1=pos,ans[cnt].s2=num;
            return i;
        }
        else{
            pos=sta[top--],c[pos]++;
            b[2-c[pos]+1][a[i]]=pos;
            d[2-c[pos]+1][pos]=a[i];
            cnt++;ans[cnt].opt=1,ans[cnt].s1=pos;
        }
    }
    return m;
}
int main(){
    freopen("meow.in","r",stdin);
    freopen("meow.out","w",stdout);
    int t;cin>>t;
    while(t--){
        cin>>n>>m>>k;num=n;
        for(int i=n-1;i>=1;i--)
            sta[++top]=i,sta[++top]=i;
        for(int i=1;i<=m;i++) cin>>a[i];
        for(int i=1;i<=m;i++){
            int opt=chk(a[i]),pos;
            if(opt) pos=fnd(opt,a[i]);
            if(opt==1){
                sta[++top]=pos,c[pos]--;
                b[1][a[i]]=0,d[1][pos]=0;
                cnt++;ans[cnt].opt=1,ans[cnt].s1=pos;
            }
            else if(opt==2&&c[pos]==1){
                sta[++top]=pos,c[pos]--;
                b[2][a[i]]=0,d[2][pos]=0;
                cnt++;ans[cnt].opt=1,ans[cnt].s1=pos;
            }
            else if(opt==2){
                sta[++top]=pos,c[pos]--;
                b[2][a[i]]=0,d[2][pos]=d[1][pos];
                d[1][pos]=0,b[1][d[2][pos]]=0;
                b[2][d[2][pos]]=pos;
                cnt++;ans[cnt].opt=1,ans[cnt].s1=num;
                cnt++;ans[cnt].opt=2,ans[cnt].s1=pos,ans[cnt].s2=num;
            }
            else if(top){
                pos=sta[top--],c[pos]++;
                b[2-c[pos]+1][a[i]]=pos;
                d[2-c[pos]+1][pos]=a[i];
                cnt++;ans[cnt].opt=1,ans[cnt].s1=pos;
            }
            else i=work(i);
        }
        cout<<cnt<<'\n';
        for(int i=1;i<=cnt;i++)
            if(ans[i].opt==1)
                cout<<ans[i].opt<<' '<<ans[i].s1<<'\n';
            else cout<<ans[i].opt<<' '<<ans[i].s1<<' '<<ans[i].s2<<'\n';
        top=cnt=0;
        for(int i=1;i<=m;i++)
            a[i]=0;
        for(int i=1;i<=n;i++)
            c[i]=d[1][i]=d[2][i]=0;
        for(int i=1;i<=k;i++)
            b[1][i]=b[2][i]=0;
    }
}
/*
2
3 10 5
1 2 3 4 5 2 3 4 5 1
2 4 2
1 2 1 2
*/

T3:

#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int N=1e9+7;
int main(){
    freopen("barrack.in","r",stdin);
    freopen("barrack.out","w",stdout);
    cout<<rand()%N<<'\n';
}

T4:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+10;
int a[N],b[N],l[2][N],r[2][N];
int main(){
    freopen("match.in","r",stdin);
    freopen("match.out","w",stdout);
    int t,n,qq;cin>>t>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) cin>>b[i];
    cin>>qq;
    for(int i=1;i<=qq;i++){
        int ll,rr,ans=0;cin>>ll>>rr;
        for(int p=ll;p<=rr;p++){
            int m1=a[p],m2=b[p];
            for(int q=p;q<=rr;q++){
                m1=max(m1,a[q]),m2=max(m2,b[q]);
                ans+=m1*m2;
            }
        }
        cout<<ans<<'\n';
    }
}
/*
0 2
2 1
1 2
1
1 2
*/

希望能混奖吧。。。