首页 > 其他分享 >2024暑假集训测试8

2024暑假集训测试8

时间:2024-07-22 09:40:00浏览次数:7  
标签:rs int sum sumr 2024 suml ls 暑假 集训

前言

image

爆零了?!?T4 莫名 CE 了,T2 因为某些人打乱搞做法使出题人改数据和时限,\(O(npk)\) 做法死掉了,主要还是数组开大了还忘了算,直接爆零了。

T1 White and Black

显然不存在无解,从根开始扫,遇到黑色就翻转,前后顺序不影响结果,该方案为正确且唯一方案。

继续观察发现若一个点与其父亲颜色不同,则产生一次贡献。

答案为 \(m+\sum\limits_{i=1}^{m}size_i-sum_i\),\(sum_i\) 指其子节点中颜色同样为黑色的个数。

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=5e5+10;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool z=true;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(z?x:~x+1);
}
void wt(int x){if(x>9)wt(x/10);putchar((x%10)+'0');}
void write(int x){if(x<0)putchar('-'),x=~x+1;wt(x);}
int n,m,fa[N],deg[N],b[N],ans;
vector<int>e[N];
signed main()
{
    read(n),read(m);
    for(int i=2;i<=n;i++) read(fa[i]),deg[fa[i]]++;
    for(int i=1,x;i<=m;i++)
    {
        read(x); ans=x;
        for(int j=1;j<=x;j++) read(b[j]),deg[fa[b[j]]]-=2;
        for(int j=1;j<=x;j++) ans+=deg[b[j]];
        for(int j=1;j<=x;j++) deg[fa[b[j]]]+=2;
        write(ans),puts("");
    }
}

T2 White and White

  • 部分分 \(10pts\):\(O(n^2k)~DP\)。

  • 部分分 \(50pts\):\(O(nkp)\),考虑对于每个前缀和同余相同的本质是相同的,对于每个模数只保存最优策略即可。本来能过的做法

  • 部分分 \(50pts\):\(O(nk\log(p))\),树状数组做法,本来是能过的,但赛时出题人发现某人该做法常数巨大十分不爽,改时限就过不去了;又因为某人直接输出 \(sum\bmod p\) 还贼不好卡,又把捆绑加上了。

  • 正解:

    先写出 \(O(n^2k)\) 的转移方程:

    \[f_{i,k}=\min\limits_{j=k-1}^{i-1}\{f_{j,k-1}+(sum_i-sum_j)\bmod p\} \]

    发现对于每个 \(f_{i,*}\) 其 \(\bmod p\) 的值恒等于 \(sum_i \bmod p\),那么对于两个转移点 \(x,y\),有:

    \[f_{x,k-1}+(sum_i-sum_x)\bmod p\equiv f_{y,k-1}+(sum_i-sum_y)\bmod p\pmod p \]

    若 \(f_{x,k-1}<f_{y,k-1}\),因为 \((sum_i-sum_j)\bmod p<p\),所以一定有 \(f_{x,k-1}+(sum_i-sum_x)\bmod p\le f_{y,k-1}+(sum_i-sum_y)\bmod p\)。

    所以直接记录最优策略即可,复杂度 \(O(nk)\)。

    点击查看代码
    #include<bits/stdc++.h>
    #define int long long 
    #define endl '\n'
    #define sort stable_sort
    using namespace std;
    const int N=5e5+10;
    template<typename Tp> inline void read(Tp&x)
    {
        x=0;register bool z=true;
        register char c=getchar();
        for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
        for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
        x=(z?x:~x+1);
    }
    void wt(int x){if(x>9)wt(x/10);putchar((x%10)+'0');}
    void write(int x){if(x<0)putchar('-'),x=~x+1;wt(x);}
    int n,m,p,f[N][2],sum[N],lastx[N],lasty[N];
    queue<pair<int,int>>q;
    signed main()
    {
        read(n),read(m),read(p);
        for(int i=1,a;i<=n;i++)
            read(a),sum[i]=sum[i-1]+a;
        memset(f,0x3f,sizeof(f));
        f[0][0]=0;
        for(int j=1;j<=m;j++)
        {
            int minn=f[j-1][(j-1)&1],ans=j-1;
            for(int i=j;i<=n;i++)
            {
                f[i][j&1]=minn+(sum[i]-sum[ans])%p;
                if(f[i][(j-1)&1]<minn) 
                {
                    minn=f[i][(j-1)&1];
                    ans=i;
                }
            }
        }
        write(f[n][m&1]);
    }
    

T3 Black and Black

直接填入 \(1\sim n\),若 \(sum=0\),直接输出即可。

若 \(sum<0\),设 \(v=0-sum\) 因为现在是满足单调递增的,要维持这个转台只能从前缀或后缀修改,那么对于一个 \(a_i\) 的前缀和与后缀和,若其存在负值前缀和,定存在前缀和为 \(-1\) 的 \(i\),另 \(1\sim i\) 全部 \(-v\)即可;同理若存在正值后缀和,定存在后缀和为 \(1\) 的 \(i\),另 \(i\sim n\) 全部 \(+v\) 即可。

反之同理。

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=5e5+10;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool z=true;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(z?x:~x+1);
}
void wt(int x){if(x>9)wt(x/10);putchar((x%10)+'0');}
void write(int x){if(x<0)putchar('-'),x=~x+1;wt(x);}
int n,a[N],sum,ans[N],pre[N],suf[N];
signed main()
{
    read(n);
    for(int i=1;i<=n;i++)
        read(a[i]),
        sum+=a[i]*i,
        pre[i]=pre[i-1]+a[i],
        ans[i]=i;
    for(int i=n;i>=1;i--)
        suf[i]=suf[i+1]+a[i];
    if(sum==0)
    {
        puts("Yes");
        for(int i=1;i<=n;i++) write(i),putchar(' ');
    }
    if(sum<0)
    {
        int v=0-sum;
        bool flag=0;
        for(int i=1;i<=n;i++)
            if(pre[i]==-1)
            {
                for(int j=1;j<=i;j++) ans[j]-=v;
                flag=1;
                break;
            }
        if(!flag)
            for(int i=n;i>=1;i--)
                if(suf[i]==1)
                {
                    for(int j=n;j>=i;j--) ans[j]+=v;
                    flag=1;
                    break;
                }
        if(!flag) puts("No");
        else 
        {
            puts("Yes");
            for(int i=1;i<=n;i++) write(ans[i]),putchar(' ');
        }
    }
    if(sum>0)
    {
        int v=sum-0;
        bool flag=0;
        for(int i=1;i<=n;i++)
            if(pre[i]==1)
            {
                for(int j=1;j<=i;j++) ans[j]-=v;
                flag=1;
                break;
            }
        if(!flag)
            for(int i=n;i>=1;i--)
                if(suf[i]==-1)
                {
                    for(int j=n;j>=i;j--) ans[j]+=v;
                    flag=1;
                    break;
                }
        if(!flag) puts("No");
        else 
        {
            puts("Yes");
            for(int i=1;i<=n;i++) write(ans[i]),putchar(' ');
        }
    }
}

T4 Black and White

  • 部分分 \(60pts\):\(O(nm)\) 暴力。

  • 正解:

    这道题方法特别多,我写的是括号序列的做法。

    括号序列指遍历一棵树的过程中进入一个节点前加一个 (,将该节点子树遍历完后加一个 ),从而与原 \(dfs\) 序得到一个括号序列。

    那么此时对于两点间的距离,截取两点之间的区间,将能够匹配上的左右括号删去,剩下的括号的个数就是两点间距离,很好理解,局限性是只能处理边权为 \(1\) 的情况。

    考虑对于动态修改的黑色点集维护树的直径,开一颗线段树,每个节点即维护对应区间 \([l,r]\) 内的直径,考虑如何维护。

    定义 \(suml,sumr\) 表示左右括号个数,每次合并左区间左括号与右区间右括号匹配,故有:

    if(t[ls].suml>t[rs].sumr)
    {
        f.suml=t[ls].suml-t[rs].sumr+t[rs].suml;
        f.sumr=t[ls].sumr;
    }
    else 
    {
        f.suml=t[rs].suml;
        f.sumr=t[ls].sumr+t[rs].sumr-t[ls].suml;
    }
    

    类似于区间子段和的操作,找到直径最大的一个子区间,故此需要维护前后缀,假设找到了那个子区间,有 \(f.dis=ls.sumr+|ls.suml-rs.sumr|+rs.suml\),故有 \(f.dis=\max((ls.suml+ls.sumr)+(rs.suml-rs.sumr),(ls.sumr-ls.suml)+(rs.suml+rs.sumr))\),不妨另 \(pre1,pre2\) 分别表示前缀 \(\max(suml+sumr),\max(suml-sumr)\),\(suf1,suf2\) 分别表示后缀的 \(\max(suml+sumr),\max(sumr-suml)\),从而有转移:

    f.dis=max({t[ls].dis,t[rs].dis,t[ls].suf1+t[rs].pre2,t[ls].suf2+t[rs].pre1});
    f.pre1=max({t[ls].pre1,t[rs].pre1+t[ls].sumr-t[ls].suml,t[rs].pre2+t[ls].suml+t[ls].sumr});
    f.pre2=max({t[ls].pre2,t[rs].pre2+t[ls].suml-t[ls].sumr});
    f.suf1=max({t[rs].suf1,t[ls].suf1+t[rs].suml-t[rs].sumr,t[ls].suf2+t[rs].suml+t[rs].sumr});
    f.suf2=max({t[rs].suf2,t[ls].suf2+t[rs].sumr-t[rs].suml});
    

    对于白点是没有意义的,另起 \(dis,pre,suf\) 均为 \(-inf\) 即可。

    修改直接单点修改即可。

    点击查看代码
    #include<bits/stdc++.h>
    #define ll long long 
    #define endl '\n'
    #define sort stable_sort
    #define f t[p]
    #define ls (p<<1)
    #define rs (p<<1|1)
    using namespace std;
    const int N=5e5+10,inf=1e9;
    template<typename Tp> inline void read(Tp&x)
    {
        x=0;register bool z=true;
        register char c=getchar();
        for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
        for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
        x=(z?x:~x+1);
    }
    template<typename Tp> inline void wt(Tp x)
    {if(x>9)wt(x/10);putchar((x%10)+'0');}
    template<typename Tp> inline void write(Tp x)
    {if(x<0)putchar('-'),x=~x+1;wt(x);}
    int n,m,tot,cnt,pos[N],dfn[N],c[N];
    vector<int>e[N];
    struct aa {int l,r,dis,suml,sumr,pre1,pre2,suf1,suf2;}t[N<<2];
    void dfs(int x,int fa)
    {
        pos[++tot]=-1; pos[++tot]=x; dfn[x]=tot;
        for(int y:e[x]) if(y!=fa) dfs(y,x);
        pos[++tot]=-2;
    }
    void push(int p,int x)
    {
        f.suml=f.sumr=0;
        f.dis=f.pre1=f.pre2=f.suf1=f.suf2=-inf;
        if(pos[x]==-1) f.suml=1;
        else if(pos[x]==-2) f.sumr=1;
        else if(c[pos[x]]==0) f.dis=f.pre1=f.pre2=f.suf1=f.suf2=0;
    }
    void pushup(int p)
    {
        if(t[ls].suml>t[rs].sumr)
        {
            f.suml=t[ls].suml-t[rs].sumr+t[rs].suml;
            f.sumr=t[ls].sumr;
        }
        else 
        {
            f.suml=t[rs].suml;
            f.sumr=t[ls].sumr+t[rs].sumr-t[ls].suml;
        }
        f.dis=max({t[ls].dis,t[rs].dis,t[ls].suf1+t[rs].pre2,t[ls].suf2+t[rs].pre1});
        f.pre1=max({t[ls].pre1,t[rs].pre1+t[ls].sumr-t[ls].suml,t[rs].pre2+t[ls].suml+t[ls].sumr});
        f.pre2=max({t[ls].pre2,t[rs].pre2+t[ls].suml-t[ls].sumr});
        f.suf1=max({t[rs].suf1,t[ls].suf1+t[rs].suml-t[rs].sumr,t[ls].suf2+t[rs].suml+t[rs].sumr});
        f.suf2=max({t[rs].suf2,t[ls].suf2+t[rs].sumr-t[rs].suml});
    }
    void build(int p,int l,int r)
    {
        f.l=l,f.r=r;
        if(l==r) {push(p,l); return ;}
        int mid=(l+r)>>1;
        build(ls,l,mid),build(rs,mid+1,r);
        pushup(p);
    }
    void change(int p,int x)
    {
        if(f.l==f.r) {push(p,x); return ;}
        int mid=(f.l+f.r)>>1;
        if(x<=mid) change(ls,x);
        else change(rs,x);
        pushup(p);
    }
    signed main()
    {
        read(n); 
        for(int i=1,a,b;i<=n-1;i++)
        {
            read(a),read(b);
            e[a].push_back(b);
            e[b].push_back(a);
        }
        dfs(1,0);
        build(1,1,tot);
        read(m); cnt=n;
        for(int i=1,x;i<=m;i++)
        {
            char op;
            cin>>op; 
            if(op=='C')
            {
                read(x);
                c[x]^=1;
                cnt+=(c[x]==0)?1:-1;
                change(1,dfn[x]);
            }
            else 
            {
                if(cnt==0) puts("-1");
                else if(cnt==1) puts("0");
                else write(t[1].dis),puts("");
            }
        }
    }
    

总结

不管什么情况记得算空间。

由于赛时被 Huge 喊回去整理内务耗费时间,但不是主要原因,因为身体不好走两趟直接虚了,状态很差。

昨天 #define int long long 被 \(D\) 了,以后不这么写了。

标签:rs,int,sum,sumr,2024,suml,ls,暑假,集训
From: https://www.cnblogs.com/Charlieljk/p/18315450

相关文章

  • 【AI资讯早报】AI科技前沿资讯概览:2024年7月22日早报
    【AI资讯早报,感知未来】AI科技前沿资讯概览,涵盖了行业大会、技术创新、应用场景、行业动态等多个方面,全面展现了AI领域的最新发展动态和未来趋势。1.欧盟推进人工智能监管立法近日,欧盟在《欧盟官方公报》上正式公布了其人工智能法案,标志着欧洲在AI监管领域迈出了重要一步。该......
  • 20240721-宝塔面板配置及博客网站搭建
    首先部署宝塔面板,并登录登录前先进行面板的配置:登录之后安装软件和环境(mysql,php,ftp,nginx等)添加一个网站,根据需求填选项网站创建完成!现在去WordPress下载源码:下载完成是个压缩包,解压:计划通过FTP服务将源码上传至服务器网站根目录但FTP连接时出现问题:经调查发现FTP服务器被动模式使......
  • 都2024年了你还傻傻分不清楚“编译时”和“运行时”吗?
    前言在写vue3编译原理揭秘电子书的时候,发现有不少粉丝还傻傻分不清楚什么是编译时?什么是运行时?这篇文章我们来让你彻底搞清楚编译时和运行时的区别。关注公众号:【前端欧阳】,给自己一个进阶vue的机会编译时我将编译这个词语理解为翻译,这句话是什么意思呢?比如你要和一个老外沟......
  • linux系统基础:查找文件 20240722
    在Shell中查找文件是一个常见的任务,可以使用多种工具来完成,例如find、locate、grep等。以下是一些使用这些工具的示例。1.使用find命令find命令是最常用的文件查找工具之一,它在指定目录及其子目录下搜索符合条件的文件。示例:查找/home/user目录下所有以.txt结尾的文件。find......
  • 坐牢第十三天 20240719
    一.笔记一.链表的引入1.1总结顺序表的优缺点1>优点:能够直接通过下标进行定位元素,访问效率高,对元素进行查找和修改比较快2>不足:插入和删除元素需要移动大量的元素,效率较低3>缺点:存储数据元素有上限,当达到MAX后,就不能再添加元素了1.2链表的概念1>链式存储的线性表叫......
  • 2024年技校大数据实验室建设及大数据实训平台整体解决方案
    随着信息技术的迅猛发展,大数据已成为推动产业升级和社会进步的重要力量。为适应市场需求,培养高素质的大数据技术人才,技校作为职业教育的重要阵地,亟需加强大数据实验室的建设与实训平台的打造。本方案旨在提出一套全面、可行的2024年技校大数据实验室建设及大数据实训平台整......
  • 干货 | 2024基于风险驱动的交付模式转型探索与实践(免费下载)
    以上是资料简介和目录,如需下载,请前往星球获取:......
  • NOI2024 游记
    \(\texttt{NOI[D]2024}\)\(\texttt{Day7/3}\)中考完了。坐火车来到了重庆。\(\texttt{Day7/4-7/12}\)模拟赛。怎么打了一场仨暴力rk1啊??怎么有个A题唐氏\(100\to0\)啊??怎么有场人均题坐牢3h不会,非人均题30min切了啊??总结:mt19937rng;intmy_rank=rng()%people_co......
  • 2024年steam好玩的新游:《哈迪斯2》《雨中冒险: 回归》等
    今天已经有不少新游上线,下面为大家整理了2024年好玩的steam游戏,一起来看看。2024值得一玩的新游1、《哈迪斯2》哈迪斯2(HadesII)是SupergiantGames继其广受好评的作品《哈迪斯》之后开发的一款动作角色扮演游戏。在《哈迪斯》中,玩家扮演冥王哈迪斯的儿子扎格列欧斯,试图逃......
  • HDU多校 2024R1
    T1把\(A\)的所有循环位移哈希一下扔set里,拿\(B\)的所有长为\(|A|\)的子串查一遍即可。代码#include<iostream>#include<set>usingnamespacestd;set<unsignedlonglong>st;constintB=2333;unsignedlonglongpw[2000005];intmain(){inttc;......