首页 > 其他分享 >2024.11.05 刷题训练

2024.11.05 刷题训练

时间:2024-11-04 22:59:32浏览次数:5  
标签:2024.11 05 int 线段 mid tot maxn now 刷题

2024.11.05 刷题训练

P7054 NWRRC2015 Graph

构造题,把拓扑序中的队列换成小根堆是最小字典序,此时设置一个大根堆,用于处理连边问题。

设 \(lst\) 是上一个拓扑序中的节点。

  1. 小根堆堆顶大于大根堆,当前位置最优解,不耗费连边数量。
  2. 小根堆堆顶小于大根堆,若 \(k\) 不为 \(0\) 加入到大根堆中并将 \(k--\),选择大根堆中的数时,需要从上一个拓扑序中的节点 \(lst\) 连一条有向边到当前点。

证明显然,将序列中靠前的位置放置了可控制范围内最大的数字。

#include<bits/stdc++.h>
using namespace std;

#define pii pair<int,int>
#define fi first
#define se second

const int maxn=1e5+5;

int n,m,k;
int ind[maxn],ans[maxn];

vector<int>E[maxn];

vector<pii>edge;

priority_queue<int>q;
priority_queue<int,vector<int>,greater<int>>p;

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        E[u].push_back(v);
        ind[v]++;
    }
    for(int i=1;i<=n;i++) if(!ind[i]) p.push(i);
    int lst=0;
    for(int i=1;i<=n;i++)
    {
        while(k&&!p.empty())
        {
            int tmp=-1;
            if(!q.empty()) tmp=q.top();
            if(p.top()>tmp&&p.size()==1) break;
            q.push(p.top());p.pop(),k--;
        }
        int now=0;
        if(!p.empty()) now=p.top(),p.pop();
        else now=q.top(),q.pop(),edge.push_back({lst,now});
        ans[i]=now;
        for(auto v:E[now]) if(!(--ind[v])) p.push(v);
        lst=now;
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    putchar('\n');
    printf("%d\n",(int)edge.size());
    for(auto v:edge) printf("%d %d\n",v.fi,v.se);
}

P7124 Ynoi2008 stcm

又是构造,妙妙题。

把一棵子树的 \(dfn\) 始末看作一条线段,按照线段左端点排序,满足条件时整个序列中除了 \([l,r]\) 中的点都是加入集合的。

考虑分治,当前处理的区间为 \([l,r]\) 时区间 \([1,l-1]\cup [r+1,n]\) 中的点已经加入集合。

求出当前的区间中点 \(mid\),将所有跨过(包括碰到)\(mid\) 的线段处理出来,由于 \(dfn\) 序良好的性质,先处理上述端点靠左的线段,发现后面处理的线段一定是前一个处理线段的子线段,不断增加集合的数即可实现上述处理。

然后递归至区间 \([l,mid]\) 和 \([mid+1,r]\)。

实现看代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+5;

struct Edge
{
    int tot;
    int head[maxn];
    struct edgenode{int to,nxt;}edge[maxn*2];
    inline void add(int x,int y)
    {
        tot++;
        edge[tot].to=y;
        edge[tot].nxt=head[x];
        head[x]=tot;
    }
}T;

int n,cok;
int dfn[maxn],ed[maxn],fdfn[maxn];

vector<int>vec;

inline void clr()
{
    for(int i=1;i<=n;i++) T.head[i]=dfn[i]=ed[i]=fdfn[i]=0;
    T.tot=cok=0;
    vec.clear();
}
inline void dfs(int u)
{
    ed[u]=dfn[u]=++cok;fdfn[cok]=u;
    vec.push_back(dfn[u]);
    for(int i=T.head[u];i;i=T.edge[i].nxt)
    {
        int v=T.edge[i].to;
        dfs(v);
        ed[u]=ed[v];
    }
}
inline void solve(int l,int r)
{
    vector<int>lv,rv;
    int ld=l-1,rd=r+1,mid=(l+r)>>1,cnt=0;
    for(auto v:vec)
    {
        if(ed[fdfn[v]]<mid) lv.push_back(v);
        else if(v>mid) rv.push_back(v);
        else
        {
            while(ld<v-1) printf("+%d",fdfn[++ld]),cnt++;
            while(rd>ed[fdfn[v]]+1) printf("+%d",fdfn[--rd]),cnt++;
            printf("=%d",fdfn[v]);
        }
    }
    if(l==r) return ;
    for(int i=1;i<=cnt;i++) printf("-");
    if(l==r) return ;
    for(int i=l;i<=mid;i++) printf("+%d",fdfn[i]);
    swap(vec,rv);
    solve(mid+1,r);
    for(int i=l;i<=mid;i++) printf("-");
    for(int i=mid+1;i<=r;i++) printf("+%d",fdfn[i]);
    swap(vec,lv);
    solve(l,mid);
    for(int i=mid+1;i<=r;i++) printf("-");
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        clr();
        for(int i=1;i<n;i++)
        {
            int u;
            scanf("%d",&u);
            T.add(u,i+1);
        }
        dfs(1);
        sort(vec.begin(),vec.end());
        solve(1,n);
        printf("!\n");
    }
}

标签:2024.11,05,int,线段,mid,tot,maxn,now,刷题
From: https://www.cnblogs.com/binbin200811/p/18526929

相关文章

  • 2024.11 做题笔记
    2024.11做题笔记其实是CSP后到NOIP前的部分10.28怎么KTSC这么困难啊……B.P11237「KTSC2024R1」警察与小偷把警察、小偷所在路径拎出来,此时警察一定往小偷所在方向走,而小偷可以在警察到路径上的某点之前从这点走向路径外,想选尽量长的路径,让警察走的尽量多但可能......
  • 2024.11.4~2024.11.9
    2024.11.4今天早上没有醒来,一抬表发现7:03了直接破防(悲上午模拟赛T1直接一个没思路,想了1h都没想出来,打了10分遗憾离场,T2直接就是死磕1h也没有丝毫思路,然后最后10分非常惨下午都在调T1,直到4点才调完,晚上情绪状态比较不稳定,但是调整的很好,还是坚持做了5到题,比较可以csp-s160分完......
  • 代码随想录刷题学习日记
    仅为个人记录复盘学习历程,解题思路来自代码随想录代码随想录刷题笔记总结网址:代码随想录559.n叉树的最大深度(层序遍历法)给定一个n叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。提供参数:根结点root关键思路:和二叉树的层序遍历找最......
  • 代码随想录刷题学习日记
    仅为个人记录复盘学习历程,解题思路来自代码随想录代码随想录刷题笔记总结网址:代码随想录递归函数什么时候需要返回值?什么时候不需要返回值?如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返......
  • 代码随想录刷题学习日记
    仅为个人记录复盘学习历程,解题思路来自代码随想录代码随想录刷题笔记总结网址:代码随想录654.最大二叉树给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右......
  • 2024.11.04
    今天心情不好,不写模拟赛了模拟赛的内容在学校写完得了,回家写小作文睡觉模拟赛没怎么好好打。第二次打构造题,这种题和其他的是真的不一样。看来我不仅要恶补各种算法,还要锻炼一下我的思维。猜猜今天有没有题目小链接T1【串】题目大意:给出n,k(1<=n,k<=1e5),要求构造出长度为n......
  • PLC QCA7005调试笔记
    方案选择SOC方案选择不多,暂时只发现高通和联芯通两家。模块方案较多,基本都是基于高通方案实现的。想要获取高通原厂的技术支持比较困难,但考虑到产品的稳定性还是选择了高通。高通:https://www.qualcomm.com/products/internet-of-things/networking/wi-fi-networks/qca7005联......
  • 2024.11.4 test
    B你可以进行以下的操作:选择一个点染白色;此后每次染有白色点相邻的,且\(a_i\)最小的点。\(q\)次询问每次给出\(p,k\),问有多少种选择点的方案,使得\(p\)是第\(k\)个选到的。\(a_i\)是排列。\(n,q\le1e5\)。设\(l=p-k+1,r=p+k-1\),若\([l,p-1]\)能取到且\(a_p<a_{l-1}......