首页 > 其他分享 >『模拟赛』暑假集训CSP提高模拟21

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

时间:2024-08-15 20:16:25浏览次数:3  
标签:__ ch 21 int qr lx CSP 模拟 dis

Rank

意外地还凑合,本来以为这场要 GG 了。

image

A. 黎明与萤火

原[CF963B] Destruction of a Tree

签,勉强签了。

开始脑子乱,胡乱打了一个含有 3 个 dfs 函数,每个函数里含两次遍历链式前向星,不负众望大样例 T 了。

后来也是摸着摸着就出正解了,先一遍 dfs 跑出基本的数据,然后再一遍 dfs 从叶子结点开始能删就删,删边操作单独进一个 dfs,最终判断能不能全删,然后输出就行了。

点击查看代码

已经优化很多了。。

#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 mod=998244353;
int n;
int fx[N],hh[N],to[N<<1],ne[N<<1],cnt;
int dfn[N],dff,pos[N],ans[N],siz[N],tot,rd[N];
bool yz[N];
namespace Wisadel
{
    void Wadd(int u,int v)
    {
        to[++cnt]=v;
        ne[cnt]=hh[u];
        hh[u]=cnt;
    }
    void Wdfs(int u,int fa)
    {
        siz[u]=(fa!=0);
        fx[u]=fa;
        dfn[u]=++dff;
        pos[dff]=u;
        for(int i=hh[u];i!=-1;i=ne[i])
        {
            int v=to[i];
            if(v==fa) continue;
            Wdfs(v,u);
            siz[u]+=1;
        }
    }
    void Wsol(int u,int fa)
    {
        if(siz[u]&1) return;
        if(yz[u]) return;
        yz[u]=1,ans[++tot]=u;
        for(int i=hh[u];i!=-1;i=ne[i])
        {
            int v=to[i];
            if(yz[v]) continue;
            if(v==fa){siz[v]--;continue;}
            siz[v]--;
            Wsol(v,u);
        }
    }
    void Wdfss(int u,int fa)
    {
        for(int i=hh[u];i!=-1;i=ne[i])
        {
            int v=to[i];
            if(v==fa) continue;
            Wdfss(v,u);
        }
        Wsol(u,fa);
    }
    short main()
    {
        n=qr; memset(hh,-1,sizeof hh); bool task=1;
        fo(i,1,n) 
        {
            int x=qr; if(!x) continue;
            Wadd(x,i),Wadd(i,x);
            rd[i]++,rd[x]++;
            if(rd[i]>2||rd[x]>2) task=0;
        }
        if(task)
        {
            if(n%2==0){printf("NO\n");return Ratio;}
            printf("YES\n");
            int st;
            fo(i,1,n) if(rd[i]<2){st=i;break;}
            Wdfs(st,0);
            fo(i,1,n) if(i%2==0) printf("%d\n",pos[i]),yz[i]=1;
            fo(i,1,n) if(!yz[i]) printf("%d\n",pos[i]);
            return Ratio;
        }
        Wdfs(1,0);
        Wdfss(1,0);
        if(tot!=n) printf("NO\n");
        else
        {
            printf("YES\n");
            fo(i,1,tot) printf("%d\n",ans[i]);
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

B. Darling Dance

原[CF1076D] Edge Deletion

小水题,但保龄。

赛时想先进行一遍 Dijkstra,记录每个点的最短路由哪些边更新来,然后最后汇总,选更新次数多的。但一这个做法本身就有漏洞,二我没判 \(k\ge m\) 的情况,所以前面 WA 后面 RE。

正解是最短路径树,即用 \(n-1\) 条边使所有的点到根节点的距离尽可能小,恰好符合本题题意。由于最终结果是一棵树,所以除根节点外,每个结点恰好对应一条边,那么只要记一下每个点是由哪条边更新而来的,最后 dfs 输出即可。

点击查看代码
#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=3e5+5;
const int mod=998244353;
int n,m,k,tot;
int hh[N],to[N<<1],ne[N<<1],id[N<<1],cnt;
ll w[N<<1],dis[N];
int ans[N];
bool yz[N];
struct rmm
{
    int to;ll w;
    bool operator<(const rmm & a) const 
    {
        return w>a.w;
    }
};
namespace Wisadel
{
    void Wadd(int _,int __,int ___,int i)
    {
        to[++cnt]=__;
        w[cnt]=___;
        id[cnt]=i;
        ne[cnt]=hh[_];
        hh[_]=cnt;
    }
    void Wdij(int x)
    {
        priority_queue<rmm>q;
        memset(dis,0x3f,sizeof dis);
        dis[x]=0;q.push({x,0});
        while(q.size())
        {
            int _=q.top().to;q.pop();
            if(yz[_]) continue;
            yz[_]=1;
            for(int i=hh[_];i!=-1;i=ne[i])
            {
                int __=to[i];
                if(dis[__]>=dis[_]+w[i])
                {
                    dis[__]=dis[_]+w[i];
                    q.push({__,dis[__]});
                    ans[__]=id[i];
                }
            }
        }
    }
    void Wdfs(int _)
    {
        for(int i=hh[_];i!=-1;i=ne[i])
        {
            int __=to[i];
            if(id[i]==ans[__])
            {
                if(++tot>k||tot==n) exit(0);
                printf("%d ",id[i]);
                Wdfs(__);
            }
        }
    }
    short main()
    {
        n=qr,m=qr,k=qr;
        memset(hh,-1,sizeof hh);
        fo(i,1,m)
        {
            int _=qr,__=qr,___=qr;
            Wadd(_,__,___,i),Wadd(__,_,___,i);
        }
        Wdij(1);
        printf("%d\n",k>n-1?n-1:k);
        Wdfs(1);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

C. Non-breath oblige

原[Ynoi2012] NOIP2015 充满了希望

还上 Ynoi 逝罢。

赛时只打出 \(\mathcal{O(nq)}\) 暴力和没有操作 2 那送的 20pts。

考虑由于出现操作 2 之前原序列不会有值,所以开线段树记录最后一次操作 2 的时间戳,每个操作就是简单的单点查询+修改,区间修改和单点查询。

将所有询问区间离线下来,对 r 做扫描线,遇到操作三就在 \(t_i\) 加上 \(v_{t_i}\) 并更新前缀,然后询问求后缀和即可,用树状数组维护,时间复杂度为 \(\mathcal{O(q\log n)}\)。

点击查看代码
#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=1e6+5;
const int mod=998244353;
int n,m,qq;
int op[N],x[N],y[N],va[N];
int t[N<<2];
ll ans[N],sum[N];
vector<pair<int,int> >q[N];
namespace Wisadel
{
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define mid ((l+r)>>1)
    inline void Wpushdown(int rt)
    {
        t[ls]=t[rs]=t[rt];
        t[rt]=0;
    }
    inline void Wupd(int rt,int l,int r,int x,int y,int k)
    {
        if(x<=l&&r<=y){t[rt]=k;return;}
        if(t[rt]) Wpushdown(rt);
        if(x<=mid) Wupd(ls,l,mid,x,y,k);
        if(y>mid) Wupd(rs,mid+1,r,x,y,k);
    }
    inline int Wq(int rt,int l,int r,int x)
    {
        if(l==r||t[rt]) return t[rt];
        if(x<=mid) return Wq(ls,l,mid,x);
        else return Wq(rs,mid+1,r,x);
    }
    inline void Wadd(int x,int va)
    {
        if(!x) return;
        while(x<=m) sum[x]+=va,x+=x&-x;
    }
    inline ll Wgsum(int x)
    {
        if(x<1) return 0;
        ll res=0;
        while(x) res+=sum[x],x^=x&-x;
        return res;
    }
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        n=qr,m=qr,qq=qr;
        fo(i,1,m)
        {
            op[i]=qr;
            if(op[i]==1)
            {
                x[i]=qr,y[i]=qr;
                int aa=Wq(1,1,n,x[i]),bb=Wq(1,1,n,y[i]);
                Wupd(1,1,n,x[i],x[i],bb),Wupd(1,1,n,y[i],y[i],aa);
            }
            else if(op[i]==2)
            {
                x[i]=qr,y[i]=qr,va[i]=qr;
                Wupd(1,1,n,x[i],y[i],i);
            }
            else
            {
                x[i]=qr;
                y[i]=Wq(1,1,n,x[i]);
            }
        }
        fo(i,1,qq)
        {
            int l=qr,r=qr;
            q[r].emplace_back(make_pair(l,i));
        }
        fo(i,1,m)
        {
            if(op[i]==3) Wadd(y[i],va[y[i]]);
            for(auto j:q[i]) ans[j.se]=Wgsum(i)-Wgsum(j.fi-1);
        }
        fo(i,1,qq) printf("%lld\n",ans[i]);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

D. 妄想感伤代偿联盟

做法好像还挺多,但是做到这时已经没啥心情打暴力了,然后直接糊了个超级 substr 上去,喜提保龄。

仍然很好题目背景,不过你都把歌曲名和歌词打出来了不放给我们听听真的合适吗qwq

赛时本来以为 T1 A不了 T2 能 A 的,结果刚好反了。因为打 T1 的时候脑子就很乱,胡乱交了个跑不过大样例的代码就去看后面的暴力了,后来强迫自己找性质结果莫名找出来了,但写得过于暴力一个代码 4 个 dfs 再加上 sb checker 乱报自测结果所以感觉拿不满,(事实上 CF 确实 WA 了一个小点

T2 想到了只跑一遍 Dijkstra 的做法,爽飞了,大样例随便跑,sb checker 莫名报 UKE,但由于 T1 的前车之鉴我并不太信这个玩意,结果是经过赛后和 GGrun 的交谈发现是做法假了。

T3 昨天找题时看到过,但没多想(正常人都不会多想的吧,好在没挂分。

下午的锣鼓 Div1 继续挂挂挂,混个 rk73,有没有有经验的佬说一下等级分 1700 这个勾式排名会扣多少分。


完结撒花~

标签:__,ch,21,int,qr,lx,CSP,模拟,dis
From: https://www.cnblogs.com/Ratio-Yinyue1007/p/18361739

相关文章

  • NSSCTF [SWPUCTF 2021 新生赛]easyupload3.0
    进入页面,是一个文件上传,放个图片马上去,用bp抓包正常进行文件上传,发现一般的后缀都被过滤了 使用.user.ini后门但好像也不行。没有什么头绪,去网上看看大佬们怎么做的。发现他们是通过修改.htaccess文件的配置来实现后门,之前也只了解过这个后缀,先去看看是干嘛的,具体怎么用。大佬......
  • 【NOIP2016普及组复赛模拟赛】侦察兵
    题目描述mxy沉迷于一个辣鸡游戏不可自拔。游戏地图是一个n*n的矩形,在每个单位格子上有一个数字,代表当前位置的生命体个数,作为一个侦察兵,mxy的任务是计算出她所在位置的左上角和右下角的总人数(不包括她所在的行列)。注意作为一个侦察兵,mxy是不包括在地图上的生命体个数中的......
  • [赛记] 暑假集训CSP提高模拟20 21
    Kanon40pts签到题,但是不会,所以打了暴力;正解时考虑相邻两个雪球,只有两种情况:它们的覆盖区间有交集或无交集,那么如果我们找出了无交集的最后一天,我们就很容易判断剩下的一堆雪该被谁拿走,于是我们二分找出这一天即可;赛时确实想不到二分时间复杂度:$\Theta(n\logn)$;点击查看......
  • CSP21
    总结:两个题的checker我都自己写了一个,MD,耽误太多时间了,\(Linux\)的\(checker\)使用要加g++checker.cpp-o程序名这题,性质题,首先发现一个树\(n-1\)条边,每次删偶数条边,所以\(n\)必须是奇数,其次我们发现优先删去深度深的点较为优,删完后,我们发现还剩下一些散点散树,再\(dfs\)一......
  • 『模拟赛』暑假集训CSP提高模拟21
    『模拟赛』暑假集训CSP提高模拟21终于没RE了!不枉我辛辛苦苦调了几个小时...(但是暴力没打完...(逃T1黎明与萤火DFS序乱糊+贪心注意要先消除叶子结点。Elaina'sCodeintn,fa[N],rdeg[N],hd[N],idx,ans[N],cnt;boolvis[N];stack<int>sta;structEDGE{ intnxt,to;}......
  • EndNote21.4安装教程(最新版)
    下载链接:https://docs.qq.com/doc/DSVZXTVRvYXdEd21q软件介绍、EndNote文献管理软件是由科睿唯安公司开发的文献管理软件,可用于帮助研究人员管理和组织参考文献、引用和注释,从文献检索、组织科研活动、撰写论文,到发表文章和共享科研成果,助力机构用户加速科研流程。EndNote......
  • 暑假集训CSP提高模拟21
    暑假集训CSP提高模拟21组题人:@Muel_imj\(T1\)P241.黎明与萤火\(10pts\)原题:CF963BDestructionofaTree部分分\(10pts\):生成\(1\simn\)的全排列然后依次判断。\(20pts\):输出NO。正解叶子节点的度数为\(1\),不能直接删除,只能先删除父亲节点后再......
  • 生态系统NPP及碳源、碳汇模拟(土地利用变化、未来气候变化、空间动态模拟)
    由于全球变暖、大气中温室气体浓度逐年增加等问题的出现,“双碳”行动特别是碳中和已经在世界范围形成广泛影响。碳中和可以从碳排放(碳源)和碳固定(碳汇)这两个侧面来理解。陆地生态系统在全球碳循环过程中有着重要作用,准确地评估陆地生态系统碳汇及碳源变化对于研究碳循环过程、预......
  • 假设Sigmund Landers在商业街设置了一个提供建议的摊位,顾客可以购买1分钟,2分钟,或3分钟
    /假设SigmundLanders在商业街设置了一个提供建议的摊位,顾客可以购买1分钟,2分钟,或3分钟的建议,为确保交通每个摊位前排队等待的顾客最多10人,用两个队列模拟两个摊位/#include<stdio.h>#include<stdlib.h>#defineMAX_SIZE10typedefstruct{intitems[MAX_SIZE];......
  • C++趣味实验之:设计一个模拟公司运营的程序(极简版)
    根据剩余价值理论,设计一个模拟公司运营的程序原理非常简单: (此公式为企业扩大再生产的基本规律)同理,我们可以利用C++来实现这个操作,这就需要使用递归函数doublen,c,sum1,d1,z1;cout<<"输入启动资金(万元):"<<endl;cin>>n;intb;cout<<"输入市场劳动力数目:"<<endl;ci......