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

Rank

非常好重测,使我 Rank--

image

A. 法阵

原[CF1503E] 2-Coloring

出题人注:原题 3100,张口放 T1

一眼高难度题,于是果断开始暴力打表,但我的打表程序十分暴力,跑 n=6,m=9 的点就已经开始硬控了,遂只拿到 30pts。

打表就不用放了吧,等我咕咕正解。

B. 连通块

同[yLCPC2024] F. PANDORA PARADOXXX

真正的 T1。

赛时由于 T1 的搞心态以及极冷的室内环境,让我几乎没有办法去想暴力以外的东西。考虑对于每次询问,对询问的该点进行 bfs,删边的话只需要在建边的时候加个序号记一下就行,可以过 50pts;然后对于链的情况,我直接用线段树维护每个区段所属的连通块序号,以及每个联通块的左右边界,实现了 O(1) 查询,O(logn) 修改,再过 10pts。

正解是倒过来做,删边操作变成建边操作,每次建边相当于一次树上启发式合并,维护树上直径信息就行了。

点击查看代码

求 LCA 用的倍增,常数较大,酌情参考。

#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 mod=998244353;
int n,m;
int hh[N],to[N<<1],ne[N<<1],cnt;
int dfn[N],dep[N],tot,fx[N][20],ans[N],ttot;
bool yz[N];
struct edge{int u,v;}e[N];
struct OP{int op,x;}p[N];
struct rmm{int fx,l,r,dis;}fa[N];
namespace Wisadel
{
    int Wfind(int x)
    {
        if(x==fa[x].fx) return x;
        return fa[x].fx=Wfind(fa[x].fx);
    }
    void Wadd(int u,int v)
    {
        to[++cnt]=v;
        ne[cnt]=hh[u];
        hh[u]=cnt;
    }
    void Wdfs(int u,int fa)
    {
        fx[u][0]=fa,dfn[u]=++tot,dep[u]=dep[fa]+1;
        fo(i,1,18) fx[u][i]=fx[fx[u][i-1]][i-1];
        for(int i=hh[u];i!=-1;i=ne[i])
        {
            int v=to[i];
            if(v==fa) continue;
            Wdfs(v,u);
        }
    }
    int Wlca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        fu(i,18,0) if((1<<i)<=dep[x]-dep[y]) x=fx[x][i];
        if(x==y) return x;
        fu(i,18,0) if(fx[x][i]!=fx[y][i]) x=fx[x][i],y=fx[y][i];
        return fx[x][0];
    }
    int Wgdis(int u,int v)
    {
        if(u==v) return 0;
        return dep[u]+dep[v]-2*dep[Wlca(u,v)];
    }
    void Wmerge(int i)
    {
        int u=Wfind(e[i].u),v=Wfind(e[i].v);
        fa[u].fx=v;
        int maxx=max(Wgdis(fa[u].l,fa[v].l),Wgdis(fa[u].l,fa[v].r));
        maxx=max(maxx,max(Wgdis(fa[u].r,fa[v].l),Wgdis(fa[u].r,fa[v].r)));
        maxx=max(maxx,max(fa[u].dis,fa[v].dis));
        if(Wgdis(fa[u].l,fa[v].l)==maxx){
            fa[v].dis=Wgdis(fa[u].l,fa[v].l),
            fa[v].r=fa[u].l;
            return;
        }
        if(Wgdis(fa[u].r,fa[v].l)==maxx){
            fa[v].dis=Wgdis(fa[u].r,fa[v].l),
            fa[v].r=fa[u].r;
            return;
        }
        if(Wgdis(fa[u].l,fa[v].r)==maxx){
            fa[v].dis=Wgdis(fa[u].l,fa[v].r),
            fa[v].l=fa[u].l;
            return;
        }
        if(Wgdis(fa[u].r,fa[v].r)==maxx){
            fa[v].dis=Wgdis(fa[u].r,fa[v].r),
            fa[v].l=fa[u].r;
            return;
        }
        if(fa[u].dis==maxx){
            fa[v].dis=fa[u].dis,
            fa[v].l=fa[u].l,fa[v].r=fa[u].r;
            return;
        }
    }
    short main()
    {
        freopen("block.in","r",stdin),freopen("block.out","w",stdout);
        n=qr,m=qr;
        memset(hh,-1,sizeof hh);
        fo(i,1,n)fa[i]={i,i,i,0};
        fo(i,1,n-1)
            e[i].u=qr,e[i].v=qr,Wadd(e[i].u,e[i].v),Wadd(e[i].v,e[i].u);
        Wdfs(1,0);
        fo(i,1,m)
        {
            p[i].op=qr,p[i].x=qr;
            if(p[i].op==1) yz[p[i].x]=1;
        }
        fo(i,1,n-1) if(!yz[i]) Wmerge(i);
        fu(i,m,1)
            if(p[i].op==1) Wmerge(p[i].x);
            else
            {
                int _=p[i].x,__=Wfind(_);
                ans[++ttot]=max(Wgdis(fa[__].l,_),Wgdis(fa[__].r,_));
            }
        fu(i,ttot,1) printf("%d\n",ans[i]);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

C. 军队

题面挺抽象的。

大概就是划分成两个问题,一是需要 O(n) 求出各队的性别情况,要用到扫描线,二是对于询问求最大值,相比而言第二步较简单些。

赛时没想到扫描线,只会 O(n3) 处理性别,遂只打暴力 20pts。

点击查看代码
#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=3e5+5;
const int mod=998244353;
int n,m,c,k,q,tmp;
ll a[N],b[N],s1[N],s2[N];
int len[N<<2],sum[N<<2],mx[N<<2];
struct rmm{int l,r,v;};
vector<rmm>upd[N];
namespace Wisadel
{
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define mid ((l+r)>>1)
    void Wpushup(int rt)
    {
        int tt=min(sum[ls],sum[rs]);
        sum[ls]-=tt,sum[rs]-=tt;
        mx[ls]-=tt,mx[rs]-=tt;
        sum[rt]+=tt;
        mx[rt]=max(mx[ls],mx[rs])+sum[rt];
    }
    void Wbuild(int rt,int l,int r)
    {
        len[rt]=r-l+1;
        if(l==r) return;
        Wbuild(ls,l,mid),Wbuild(rs,mid+1,r);
    }
    void Wupd(int rt,int l,int r,int x,int y,int v)
    {
        if(x<=l&&r<=y){sum[rt]+=v,mx[rt]+=v;return;}
        if(x<=mid) Wupd(ls,l,mid,x,y,v);
        if(y>mid) Wupd(rs,mid+1,r,x,y,v);
        Wpushup(rt);
    }
    int Wq(int rt,int l,int r,int x)
    {
        x+=sum[rt];
        if(x>=k) return len[rt];
        if(l==r) return 0;
        int res=0;
        if(mx[ls]+x>=k) res+=Wq(ls,l,mid,x);
        if(mx[rs]+x>=k) res+=Wq(rs,mid+1,r,x);
        return res;
    }
    #undef mid
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        freopen("army.in","r",stdin),freopen("army.out","w",stdout);
        n=qr,m=qr,c=qr,k=qr,q=qr;
        fo(i,1,c)
        {
            int x=qr,y=qr,xx=qr,yy=qr;
            upd[x].push_back({y,yy,1});
            upd[xx+1].push_back({y,yy,-1});
        }
        Wbuild(1,1,m);
        fo(i,1,n)
        {
            for(auto x:upd[i]) Wupd(1,1,m,x.l,x.r,x.v);
            int tt=Wq(1,1,m,0);
            a[i]=m-tt;
            b[i]=min(a[i],m-a[i]);
        }
        sort(b+1,b+1+n);
        fo(i,1,n) s1[i]=s1[i-1]+b[i]*b[i],s2[i]=s2[i-1]+b[i];
        while(q--)
        {
            int x=qr,y=qr,mid=y/2;
            int pos=upper_bound(b+1,b+1+n,mid)-b;
            if(pos==n+1)
                printf("%lld\n",1ll*((s2[n]-s2[n-x])*y-(s1[n]-s1[n-x])));
            else if(pos<=n-x+1)
                printf("%lld\n",1ll*x*(y-mid)*mid);
            else printf("%lld\n",1ll*(n-pos+1)*(y-mid)*mid+1ll*(s2[pos-1]-s2[n-x])*y-1ll*(s1[pos-1]-s1[n-x]));
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

D. 棋盘

逆天要 4 个栈。

一眼简单,再一眼困难。

可恶啊赛时没想到过河卒(忘得挺彻底的,遂只打暴力 bfs,只过 n=2 的 10pts。

用过河卒的方法每次清空 dp 数组可以拿到 30pts 的暴力分。

40pts 代码
#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=1e5+5;
const int mod=998244353;
int n,q,to,ans;
int dh[N][22],st=1,ed;
int yz[N][22],f[N][22];
namespace Wistask
{
    void Wdfs(int nowh,int nowl)
    {
        if(nowh==ed)
        {
            if(nowl==to) ans=(ans+1)%mod;
            return;
        }
        if(nowl==1)
        {
            if(dh[nowh+2][2]!=1) Wdfs(nowh+2,2);
            return;
        }
        else
        {
            if(dh[nowh+2][1]!=1) Wdfs(nowh+2,1);
            return;
        }
    }
    short main()
    {
        while(q--)
        {
            string op,s;cin>>op;
            if(op=="Add")
            {
                cin>>s;ed++;
                fo(i,0,n-1) dh[ed][i+1]=(s[i]=='#');
            }
            else if(op=="Del") st++;
            else
            {
                int a=qr;to=qr;ans=0;
                if(st>ed||(ed-st)&1||dh[st][a]==1){printf("0\n");continue;}
                Wdfs(st,a);
                printf("%d\n",ans);
            }
        }
        return Ratio;
    }
}
namespace Wisadel
{
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        freopen("chess.in","r",stdin),freopen("chess.out","w",stdout);
        n=qr,q=qr;
        // printf("%lf\n",1.0*sizeof(dh)/1024/1024);
        if(n==1)
        {
            while(q--)
            {
                string op,s;cin>>op;int a,b;
                if(op=="Add") cin>>s;
                else if(op=="Del") continue;
                else a=qr,b=qr,printf("0\n");
            }
            return Ratio;
        }
        if(n==2) return Wistask::main();
        while(q--)
        {
            string op,s;cin>>op;
            if(op=="Add")
            {
                cin>>s;ed++;
                fo(i,0,n-1) dh[ed][i+1]=(s[i]=='#');
            }
            else if(op=="Del") st++;
            else
            {
                int a=qr;to=qr;ans=0;
                memset(f,0,sizeof f);
                if(dh[st][a]!=1) f[st][a]=1;
                else {printf("0\n");continue;}
                fo(i,st+1,ed) fo(j,1,n)
                {
                    if(dh[i][j]) continue;
                    if(i-st>=2)
                    {
                        if(j>1) f[i][j]=(f[i][j]+f[i-2][j-1])%mod;
                        if(j+1<=n) f[i][j]=(f[i][j]+f[i-2][j+1])%mod;
                    }
                    if(i-st>=1)
                    {
                        if(j>2) f[i][j]=(f[i][j]+f[i-1][j-2])%mod;
                        if(j+2<=n) f[i][j]=(f[i][j]+f[i-1][j+2])%mod;
                    }
                }
                printf("%d\n",f[ed][to]);
            }
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

直接从 CSP 模拟晋升到 NOIP 模拟,难度直线上升。

看到 pdf 就觉得不对劲了,不是牛犇外校大佬出题就是逆天私题,果然被薄纱了。

打暴力手法还有欠缺,不过好在今天学到了新(确信 东西——树上连通块转移直径,不算荒了。

越来越冷了,虽然空调不直对着我(要真直对着估计早寄了,感觉这样下去过几天就也感冒发烧了,悲。


完结撒花~

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