Skip to content

泉州一中信息学Blog

信息学奥赛技术分享博客

  • 登录
  • 小学oj
  • 中学oj
  • 测试页面1
  • Toggle search form

NAN.NAN.NAN DAY 4

Posted on 2024年11月13日 By 张, 高畅 NAN.NAN.NAN DAY 4无评论

你家网络怎么这么卡。

日常膜拜360小广告,因为它比我发挥稳定的多。

[T1]

真·STL大法好。

配上 C++11 开始支持的 auto 类型,整个代码非常清爽。

感谢出题人没有要求求排名,否则只能手写了

时间复杂度 O(n \log n)

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n;
set<int>S;
int main()
{
    freopen("set.in","r",stdin);
    freopen("set.out","w",stdout);
    scanf("%d",&n);
    while(n--)
    {
        int op,x;
        scanf("%d%d",&op,&x);
        if(op==1)S.insert(x);
        else if(op==2)
        {
            if(S.count(x))S.erase(x);
        }
        else if(op==3)puts(S.count(x)?"yes":"no");
        else if(op==4)
        {
            auto it=S.lower_bound(x);
            printf("%d\n",(it==S.end())?-1:*it);
        }
        else if(op==5)
        {
            auto it=S.upper_bound(x);
            printf("%d\n",(it==S.end())?-1:*it);
        }
        else if(op==6)
        {
            auto it=S.lower_bound(x);
            if(it!=S.end()&&*it==x)printf("%d\n",x);
            else printf("%d\n",(it==S.begin()&&*it>x)?-1:*(--it));
        }
        else if(op==7)
        {
            auto it=S.lower_bound(x);
            printf("%d\n",(it==S.begin()&&*it>=x)?-1:*(--it));
        }
    }
    return 0;
}

[T2]

神秘贪心/猜结论题。

显然我们要一个人一直出牌直到出到只剩一张。

然后找他逆时针最近且牌数大于 1 的,重复以上过程。

时间复杂度 O(n),注意需要开启 __int128

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef __int128 LN;
int n,a[N];
LN res;
void print(LN x)
{
    if(x>9)print(x/10);
    putchar(x%10+48);
}
int main()
{
    freopen("poker.in","r",stdin);
    freopen("poker.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    if(a[1]==1)
    {
        puts("1");
        return 0;
    }
    if(a[1]>1)res+=(LN)(a[1]-1);
    int flag=1;
    for(int i=n;i>1;i--)
    {
        if(a[i]>1)
        {
            if(flag==1)res--;
            res+=(LN)(a[i]-1);
            flag=i;
        }
    }
    print(res*(LN)n+(LN)flag);
    return 0;
}

[T3]

似乎是 原?

但是忘了。

首先有一个结论,一直操作一个点使得全图变成同一个颜色是最优的,此时需要的步数是显然的,只需要一遍 BFS 求离这个点最大距离即为操作此点的答案。

时间复杂度 O(n^2+nm) ,大概是 O(n^3) 量级的。

#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
const int N=505,M=125005;
typedef pair<int,int> PII;
int n,m,color[N],res=1e9,par[N],ce[N][N];
PII E[M];
vector<int>G[N];
int find(int x)
{
    if(par[x]==x)return x;
    else return par[x]=find(par[x]);
}
int d[N],st[N]; 
int bfs(int S)
{
    queue<int>q;
    memset(d,0x3f,sizeof d);
    memset(st,0,sizeof st);
    d[S]=0;
    q.push(S);
    int res=0;
    while(q.size())
    {
        int u=q.front();
        q.pop();
        if(st[u])continue;
        st[u]=1;
        res=max(res,d[u]);
        for(auto j:G[u])
        {
            if(d[j]>d[u]+1)
            {
                d[j]=d[u]+1;
                q.push(j);
            }
        }
    }
    return res;
}
int main()
{
    freopen("tutu.in","r",stdin);
    freopen("tutu.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&color[i]);
        par[i]=i;
    }
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        E[i]={a,b};
        if(color[a]==color[b])
        {
            a=find(a),b=find(b);
            if(a<b)swap(a,b);
            if(a!=b)par[a]=b;
        }
    }
    for(int i=1;i<=m;i++)
    {
        int a=E[i].x,b=E[i].y;
        if(color[a]!=color[b])
        {
            a=find(a),b=find(b);
            if(!ce[a][b]&&!ce[b][a])
            {
                G[a].push_back(b);
                G[b].push_back(a);
                ce[a][b]=ce[b][a]=1;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(par[i]==i)res=min(res,bfs(i));
    }
    printf("%d",res);
    return 0;
}

[T4]

判定为 不会写DP导致的。

首先考虑 m=n-1 的情况,即这个图形成了一棵树。

此时可以直接上树形DP,设 f_{i,0/1} 代表以 i 为根的子树中,不选或选择 i 这个点所能获得的最大收益。

有转移方程式:
$f{u,0}=\sum{j \in son(u)} \max(f{j,0},f{j,1})f{u,1}=\sum{j \in son(u)} f_{j,0}$

跳过 m=n 的情况,直接考虑正解。

将每个环进行缩点(是的我这一步就不会),重新定义DP状态,其中 f_{i,0/1} 代表以第 i 个环离根最近的那一个点选不选。

至于这个状态怎么算,就直接在环上断掉一条边跑区间DP。

注意细节与常数,期望复杂度 O(n+m)

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,M=2200005;
typedef long long LL;
const LL INF=1e15;
typedef pair<int,int>PII;
#define x first
#define y second
int n,m;
int h[N],hs[N],e[M],ne[M],idx;
PII E[M];
LL w[N],f[N][2],g[N][2],NOT[N],YES[N];
void add(int h[],int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int stk[N],top,id[N],cnt,in_stk[N],st[N];
vector<int>cir[N];
void dfs(int u,int father)
{
    stk[++top]=u;
    st[u]=in_stk[u]=1;
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j==father)continue;
        if(in_stk[j])
        {
            cir[++cnt].push_back(j);
            id[j]=cnt; 
            for(int k=top;stk[k]!=j;k--)
            {
                cir[cnt].push_back(stk[k]);
                id[stk[k]]=cnt;
            }
        }
        if(!st[j])dfs(j,u);
    }
    in_stk[u]=0; 
    top--;
}
void DP(int u,int father)
{
    /*
    DP DP ON LINK
    */
    //for(auto i:cir[u])printf("%d ",i);
    //puts("");
    for(int i=hs[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j==father)continue;
        DP(j,u);
    }
    if(cir[u].size()==1)
    {
        f[u][0]=0;
        f[u][1]=w[cir[u].back()];
        for(int i=h[cir[u].back()];~i;i=ne[i])
        {
            f[u][0]+=max(f[id[e[i]]][0],f[id[e[i]]][1]);
            f[u][1]+=f[id[e[i]]][0];
        }
    }
    else
    {
        int S=cir[u].size();
        for(int i=0;i<S;i++)
        {
            int cur=cir[u][i];
            NOT[i]=YES[i]=0;
            for(int j=h[cur];~j;j=ne[j])
            {
                YES[i]+=f[id[e[j]]][0];
                NOT[i]+=max(f[id[e[j]]][0],f[id[e[j]]][1]);
            }
        }
        g[0][0]=NOT[0];//g[0][1]=YES[0]+w[cir[u][0]];
        g[0][1]=-INF;
        for(int i=1;i<S;i++)
        {
            int cur=cir[u][i];
            g[i][0]=g[i][1]=0;
            g[i][0]=max(g[i-1][0],g[i-1][1])+NOT[i];
            g[i][1]=g[i-1][0]+YES[i]+w[cur];
        }
        f[u][0]=max(g[S-1][0],g[S-1][1]);
        g[0][0]=-INF;//g[0][0]=NOT[0];
        g[0][1]=YES[0]+w[cir[u][0]];
        for(int i=1;i<S;i++)
        {
            int cur=cir[u][i];
            g[i][0]=g[i][1]=0;
            g[i][0]=max(g[i-1][0],g[i-1][1])+NOT[i];
            g[i][1]=g[i-1][0]+YES[i]+w[cur];
        }
        f[u][1]=g[S-1][0];

    }
    //printf("==%d %lld %lld\n",u,f[u][0],f[u][1]);
}
int main()
{
    freopen("bamboo.in","r",stdin);
    freopen("bamboo.out","w",stdout);
    memset(h,-1,sizeof h);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&w[i]);
    for(int i=1,a,b;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        E[i]={a,b};
        add(h,a,b);
        add(h,b,a);
    }
    dfs(1,-1);
    for(int i=1;i<=n;i++)
    {
        if(!id[i])cir[id[i]=++cnt].push_back(i);
    }
    memset(h,-1,sizeof h);
    memset(hs,-1,sizeof hs);
    idx=0;
    for(int i=1;i<=m;i++)
    {
        int a=E[i].x,b=E[i].y;
        if(id[a]!=id[b])
        {
            add(h,a,b);
            add(h,b,a);
            add(hs,id[a],id[b]);
            add(hs,id[b],id[a]);
        }
    }
    DP(id[1],-1);
    printf("%lld\n",max(f[id[1]][0],f[id[1]][1]));
    return 0;
}
训练日志

文章导航

Previous Post: NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYZ DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY4
Next Post: yNiazNhaoNng D5

发表回复 取消回复

要发表评论,您必须先登录。

2025年 6月
一 二 三 四 五 六 日
 1
2345678
9101112131415
16171819202122
23242526272829
30  
« 2月    

2024常州 Class Classic OI Problems Contest cqr的长乐集训2023 CZYZ LOC New Game NOI NOIP Password Protected PM_PK Preview Problems Retrospect Selfmade Qusetion STL The end Training Uneasy Problem 蒟蒻 通报

  • 训练日志
  • 链表
  • 入门
  • 模拟
  • dfs序
  • 并查集
  • spfa
  • 最小割
  • 矩阵树定理
  • 仙人掌
  • BSGS
  • 凸包
  • 回文自动机
  • 递推与动归
  • 堆
  • 莫队算法
  • ST表
  • Treap
  • 树套树
  • 可持久化线段树
  • 初赛
  • 搜索
  • 贪心
  • 深度优先搜索
  • 欧拉图
  • dijkstra
  • 费用流
  • 哈夫曼树
  • kruskual
  • 置换
  • 旋转卡壳
  • KMP
  • 区间动归
  • STL
  • 链表
  • 可并堆
  • sply
  • 主席树
  • 可持久化字典树
  • 算法
  • 动态规划
  • 构造
  • 广度优先搜索
  • 最短路
  • floyd
  • 最大流
  • 虚树
  • prim
  • 筛法
  • 半平面交
  • 字典树
  • 背包动归
  • 基础数据结构
  • 分块
  • 线段树
  • 替罪羊树
  • K-DTree
  • 图论
  • 二分法
  • 迭代搜索
  • 拓扑排序
  • 有上下界网络流
  • 生成树
  • 快速幂
  • 后缀数组
  • 树形动归
  • 哈希表
  • 中级数据结构
  • 平衡树
  • 可持久化数据结构
  • 数据结构
  • 三分法
  • 启发式搜索
  • 图的连通
  • 点分治
  • 博弈论
  • AC自动机
  • 状压动归
  • 单调栈
  • 树状数组
  • 高级数据结构
  • OI资料
  • 数学
  • 高精度
  • 差分约束
  • 树上倍增
  • 素数测试
  • 后缀自动机
  • 数位动归
  • 单调队列
  • 新闻
  • 几何
  • 随机化
  • 二分图染色
  • 树链剖分
  • 欧拉函数
  • manacher
  • 斜率优化
  • 离线处理
  • 信息学奥赛学长风采
  • 字符串
  • 二分图匹配
  • prufer编码
  • 卡特兰数
  • 密码学
  • 决策单调
  • 赛后总结
  • 其他
  • 2-SAT
  • 最近公共祖先
  • 矩阵乘法
  • 记忆化搜索
  • 网络流
  • Link cut tree
  • 排列组合
  • 树
  • 高斯消元
  • 乘法逆元
  • 容斥原理
  • 调和级数
  • 概率与期望
  • 模线性方程组
  • 莫比乌斯反演
  • 快速傅里叶变换
  • 扩展欧几里德
  • 最大公约数与最小公倍数

近期文章

  • DP杂题
  • 2025年2月13日模拟赛
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 3
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 2
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 1

近期评论

归档

  • 2025年2月
  • 2025年1月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月

Copyright © 2025 泉州一中信息学Blog.

Powered by PressBook WordPress theme