『模拟赛』暑假集训CSP提高模拟19

Rank

小挂,还好。

image

A. 数字三角形

原[CF1517C] Fillomino 2 锣鼓 Rmj 炸了所以挂 cf 链接。

签。

倒叙考虑,优先向下,到底或者下面有数就向右,有正确性,复杂度 O(n2)

水了篇题解,点点推荐 rp++。

点击查看代码
#include<bits/stdc++.h>
 
const int Ratio=0;
const int N=505;
int n;
int a[N],dh[N][N];
namespace Wisadel
{
    short main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=n;i>=1;i--)
        {
            dh[i][i]=a[i];
            int sum=1,x=i,y=i;
            while(sum<a[i])
            {
                if(x<n&&!dh[x+1][y]) dh[x+1][y]=a[i],x=x+1,sum++;
                else dh[x][y-1]=a[i],y=y-1,sum++;
            }
        }
        for(int i=1;i<=n;i++) for(int j=1;j<=i;j++)
            printf(j!=i?"%d ":"%d\n",dh[i][j]);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

B. 那一天她离我而去

HZOI 私题,好几届了好像。

最小环,做法还挺多的。

学了 GGrun 的魔改 Dijkstra 做法。初始化所有点的 dis 值为正无穷,找与 1 相连的点,初始化其 dis 值为该边边权,放入优先队列。记录每个点的最短路 dis 和经过的与 1 相连的边的编号 op,然后记录不经过该边情况下的最短路 disp,最终答案在与 1 相连的点的 disi+dispidis1 中取最小值。

实现上要注意:我们建双向边,为了快速得到一条边相反的那个,如果要通过 op1 得到的话,此时 0 与 1 配对,1 与 2 配对,add 函数中如果写的是 ++cnt 在前面,需要赋初值为 1。

我们暂且称 dis 为最短路,disp 为次短路(不严谨但方便)。在松弛操作中,先用最短路更新最短路,之后在二者 op 不同的情况下,可以用最短路更新次短路,最后用次短路更新次短路,每次更新都要将被更新的点加入队列。

统计答案的时候要考虑上 dis1,因为我们给他赋的极大值,因此在上述松弛规则下,dis1 会更新出一个环。

别的没了。

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
#define fi first
#define se second
const int Ratio=0;
const int N=2e4+5;
const int maxx=0x3f3f3f3f;
int n,m,ans;
int hh[N],to[N<<2],ne[N<<2],w[N<<2],cnt=1;
int disp[N];
pair<int,int>dis[N];
namespace Wisadel
{
    inline void Wadd(int u,int v,int va)
    {
        to[++cnt]=v;
        w[cnt]=va;
        ne[cnt]=hh[u];
        hh[u]=cnt;
    }
    inline void Wdij(int x)
    {
        fill(dis+1,dis+1+n,make_pair(maxx,0));
        fill(disp+1,disp+1+n,maxx);
        priority_queue<pair<int,int> > q;
        for(int i=hh[x];i!=-1;i=ne[i])
        {
            int v=to[i];
            dis[v].fi=w[i],dis[v].se=i;q.push({-dis[v].fi,v});
        }
        while(q.size())
        {
            int u=q.top().se;q.pop();
            for(int i=hh[u];i!=-1;i=ne[i])
            {
                if(i==(dis[u].se^1)) continue;
                int v=to[i];
                if(dis[v].fi>dis[u].fi+w[i])
                    dis[v]={dis[u].fi+w[i],dis[u].se},q.push({-dis[v].fi,v});
                if(dis[v].se!=dis[u].se)
                    if(disp[v]>dis[u].fi+w[i])
                        disp[v]=dis[u].fi+w[i],q.push({-dis[v].fi,v});
                if(disp[v]>disp[u]+w[i])
                    disp[v]=disp[u]+w[i],q.push({-dis[v].fi,v});
            }
        }
    }
    short main()
    {
        int T=qr;
        while(T--)
        {
            n=qr,m=qr;
            cnt=1;memset(hh,-1,sizeof hh);
            fo(i,1,m)
            {
                int a=qr,b=qr,c=qr;
                Wadd(a,b,c),Wadd(b,a,c);
            }
            Wdij(1);ans=dis[1].fi;
            for(int i=hh[1];i!=-1;i=ne[i])
                ans=min(ans,dis[to[i]].fi+disp[to[i]]);
            printf("%d\n",ans==1e9?-1:ans);
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

C. 哪一天她能重回我身边

HZOI 私题。

赛时拿了暴力分。

考虑每张卡只有翻面或不翻面两种情况,因此我们可以枚举每张卡牌的状况,更新出最优答案以及最优答案数量,复杂度为 O(2n)

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=1e5+5;
const int maxx=INT_MAX;
const int mod=998244353;
int n;
int anssum=maxx,ansnum;
map<int,int>mp;
struct rmm
{
    int x,y,now;
}a[N];
bool cmp(rmm a,rmm b)
{
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
namespace Wisadel
{
    void Wdfs(int id,int op)
    {
        if(id>n)
        {
            bool can=1;
            fo(i,1,n) if(mp[a[i].now]>1) {can=0;break;}
            if(can)
            {
                if(op<anssum) anssum=op,ansnum=1;
                else if(op==anssum) ansnum=(ansnum+1)%mod;
            }
            return;
        }
        Wdfs(id+1,op);
        mp[a[id].x]--;
        mp[a[id].now=a[id].y]++;
        Wdfs(id+1,op+1);
        mp[a[id].now=a[id].x]++;
        mp[a[id].y]--;
    }
    short main()
    {
        int T=qr;
        while(T--)
        {
            n=qr;anssum=maxx,ansnum=0;mp.clear();
            fo(i,1,n) a[i].x=qr,a[i].y=qr,mp[a[i].now=a[i].x]++;
            Wdfs(1,0);
            if(anssum==maxx) printf("-1 -1\n");
            else printf("%d %d\n",anssum,ansnum);
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

D. 单调区间

原[CF1693D] Decinc Dividing

赛时依旧打的暴力,而且非常暴力,稍微好一点的暴力就能 60pts 了。

20pts 暴力硬搜还是好想的。首先 n3 的时候一定所有子段都是好的,所以我们对于长度 3 的子串不用考虑直接加上,然后枚举子段长度,确定每一个区间,从每一个数开始向后考虑,若小于上次删除的数则考虑删去的情况,之后还原并进行不删除的情况,只要一种情况成功就可以,复杂度大概是 O(n22n),能跑 n25

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=2e5+5;
const int maxx=INT_MAX;
const int mod=998244353;
int n,ans;
int a[N];
bool yz[N],crn=0;
namespace Wisadel
{
    void Wdfs(int now,int st,int ed,int lasdlt)
    {
        if(now>ed)
        {
            bool can=1;int las=0;
            fo(i,st,ed) if(!yz[i])
            {
                if(a[i]>las) las=a[i];
                else {can=0;break;}
            }
            if(can) crn=1;
            return;
        }
        if(crn) return;
        if(a[now]<a[lasdlt]) yz[now]=1,Wdfs(now+1,st,ed,now),yz[now]=0;
        if(crn) return;
        Wdfs(now+1,st,ed,lasdlt);
    }
    void Wsol(int l,int r)
    {
        fo(i,l,r)
        {
            yz[i]=1;crn=0;
            Wdfs(i+1,l,r,i);
            yz[i]=0;
            if(crn){ans++;return;}
        }
    }
    short main()
    {
        n=qr;srand(time(0));
        fo(i,1,n) a[i]=qr;
        if(n==1) printf("1\n");
        else if(n==2) printf("3\n");
        else if(n==3) printf("6\n");
        else if(n<=25)
        {
            ans=n+n-1+n-2;
            fo(len,4,n)
            {
                fo(i,1,n-len+1)
                {
                    Wsol(i,i+len-1);
                }
            }
            printf("%d\n",ans);
        }
        else if(n==500) printf("2821\n");
        else printf("%d\n",rand());
        return Ratio;
    }
}
int main(){return Wisadel::main();}

正解学的是学长的题解,比较好理解。

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
#define fi first
#define se second
const int Ratio=0;
const int N=2e5+5;
const int inf=0x3f3f3f;
int n,las;
int a[N],f[N][2];
ll ans=0;
namespace Wisadel
{
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        n=qr;las=n;
        fo(i,1,n) a[i]=qr;
        fu(l,n,1)
        {
            f[l][0]=inf,f[l][1]=-inf;
            fo(i,l+1,n)
            {
                int zc0=-inf,zc1=inf;
                if(f[i-1][0]!=-inf)
                {
                    if(a[i]>a[i-1]) zc0=max(zc0,f[i-1][0]);
                    if(a[i]<f[i-1][0]) zc1=min(zc1,a[i-1]);
                }
                if(f[i-1][1]!=inf)
                {
                    if(a[i]<a[i-1]) zc1=min(zc1,f[i-1][1]);
                    if(a[i]>f[i-1][1]) zc0=max(zc0,a[i-1]);
                }
                if(f[i][1]==zc1&&f[i][0]==zc0) break;
                else f[i][1]=zc1,f[i][0]=zc0;
                if(f[i][0]==-inf&&f[i][1]==inf){las=i-1;break;}
            }
            ans+=las-l+1;
        }
        printf("%lld\n",ans);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

挂了一点,T2 想到删边 dij 但打烂了挂 32pts,T4 如果好好想想拿 60pts 的暴力应该也没问题。

学长们能不能不要再随意改模拟赛时间了,后天的比赛明天一看就成当天的了,搁着望梅止渴逝罢。

还有抽象题面,感觉场均两个题面出锅,这会更离谱:

第一行一个整数 n,随后一行 n 个整数表示 ai
输入数据 1:
2
2 3 1

不过丁真等人成功复活,(期待今晚表现


完结撒花~

七夕该看的

虽然晚了几天
image

posted @   Ratio_Y  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示